tty_lock: Localise the lock
In each remaining case the tty_lock is associated with a specific tty. This means we can now lock on a per tty basis. We do need tty_lock_pair() for the pty case. Uglier but still a step in the right direction. [fixed up calls in 3 missing drivers - gregkh] Signed-off-by: Alan Cox <alan@linux.intel.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d739e65bb2
commit
d29f3ef39b
15 changed files with 155 additions and 103 deletions
|
@ -1859,9 +1859,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
|
||||||
printk("block_til_ready blocking: ttys%d, count = %d\n",
|
printk("block_til_ready blocking: ttys%d, count = %d\n",
|
||||||
info->line, state->count);
|
info->line, state->count);
|
||||||
#endif
|
#endif
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
schedule();
|
schedule();
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
current->state = TASK_RUNNING;
|
current->state = TASK_RUNNING;
|
||||||
remove_wait_queue(&info->open_wait, &wait);
|
remove_wait_queue(&info->open_wait, &wait);
|
||||||
|
|
|
@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
|
||||||
if (!retinfo)
|
if (!retinfo)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
memset(&tmp, 0, sizeof(tmp));
|
memset(&tmp, 0, sizeof(tmp));
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
tmp.line = tty->index;
|
tmp.line = tty->index;
|
||||||
tmp.port = state->port;
|
tmp.port = state->port;
|
||||||
tmp.flags = state->tport.flags;
|
tmp.flags = state->tport.flags;
|
||||||
|
@ -1042,7 +1042,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
|
||||||
tmp.close_delay = state->tport.close_delay;
|
tmp.close_delay = state->tport.close_delay;
|
||||||
tmp.closing_wait = state->tport.closing_wait;
|
tmp.closing_wait = state->tport.closing_wait;
|
||||||
tmp.custom_divisor = state->custom_divisor;
|
tmp.custom_divisor = state->custom_divisor;
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
|
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1059,12 +1059,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
|
||||||
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
|
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
|
change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
|
||||||
new_serial.custom_divisor != state->custom_divisor;
|
new_serial.custom_divisor != state->custom_divisor;
|
||||||
if (new_serial.irq || new_serial.port != state->port ||
|
if (new_serial.irq || new_serial.port != state->port ||
|
||||||
new_serial.xmit_fifo_size != state->xmit_fifo_size) {
|
new_serial.xmit_fifo_size != state->xmit_fifo_size) {
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1084,7 +1084,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_serial.baud_base < 9600) {
|
if (new_serial.baud_base < 9600) {
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1116,7 +1116,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
retval = startup(tty, state);
|
retval = startup(tty, state);
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1599,7 +1599,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
|
||||||
* If the port is the middle of closing, bail out now
|
* If the port is the middle of closing, bail out now
|
||||||
*/
|
*/
|
||||||
if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
|
if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
|
||||||
wait_event_interruptible_tty(info->port.close_wait,
|
wait_event_interruptible_tty(tty, info->port.close_wait,
|
||||||
!(info->port.flags & ASYNC_CLOSING));
|
!(info->port.flags & ASYNC_CLOSING));
|
||||||
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
|
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1065,7 +1065,8 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
|
||||||
|
|
||||||
TRACE_L("read()");
|
TRACE_L("read()");
|
||||||
|
|
||||||
tty_lock();
|
/* FIXME: should use a private lock */
|
||||||
|
tty_lock(tty);
|
||||||
|
|
||||||
pClient = findClient(pInfo, task_pid(current));
|
pClient = findClient(pInfo, task_pid(current));
|
||||||
if (pClient) {
|
if (pClient) {
|
||||||
|
@ -1077,7 +1078,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
/* block until there is a message: */
|
/* block until there is a message: */
|
||||||
wait_event_interruptible_tty(pInfo->read_wait,
|
wait_event_interruptible_tty(tty, pInfo->read_wait,
|
||||||
(pMsg = remove_msg(pInfo, pClient)));
|
(pMsg = remove_msg(pInfo, pClient)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1107,7 +1108,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
|
||||||
}
|
}
|
||||||
ret = -EPERM;
|
ret = -EPERM;
|
||||||
unlock:
|
unlock:
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1156,7 +1157,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
|
||||||
pHeader->locks = 0;
|
pHeader->locks = 0;
|
||||||
pHeader->owner = NULL;
|
pHeader->owner = NULL;
|
||||||
|
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
|
|
||||||
pClient = findClient(pInfo, task_pid(current));
|
pClient = findClient(pInfo, task_pid(current));
|
||||||
if (pClient) {
|
if (pClient) {
|
||||||
|
@ -1175,7 +1176,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
|
||||||
add_tx_queue(pInfo, pHeader);
|
add_tx_queue(pInfo, pHeader);
|
||||||
trigger_transmit(pInfo);
|
trigger_transmit(pInfo);
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
|
||||||
wake_up_interruptible(&tty->read_wait);
|
wake_up_interruptible(&tty->read_wait);
|
||||||
wake_up_interruptible(&tty->write_wait);
|
wake_up_interruptible(&tty->write_wait);
|
||||||
tty->packet = 0;
|
tty->packet = 0;
|
||||||
|
/* Review - krefs on tty_link ?? */
|
||||||
if (!tty->link)
|
if (!tty->link)
|
||||||
return;
|
return;
|
||||||
tty->link->packet = 0;
|
tty->link->packet = 0;
|
||||||
|
@ -62,9 +63,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
|
||||||
mutex_unlock(&devpts_mutex);
|
mutex_unlock(&devpts_mutex);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
tty_unlock();
|
|
||||||
tty_vhangup(tty->link);
|
tty_vhangup(tty->link);
|
||||||
tty_lock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,26 +621,29 @@ static int ptmx_open(struct inode *inode, struct file *filp)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* find a device that is not in use. */
|
/* find a device that is not in use. */
|
||||||
tty_lock();
|
mutex_lock(&devpts_mutex);
|
||||||
index = devpts_new_index(inode);
|
index = devpts_new_index(inode);
|
||||||
tty_unlock();
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
retval = index;
|
retval = index;
|
||||||
goto err_file;
|
goto err_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&devpts_mutex);
|
||||||
|
|
||||||
mutex_lock(&tty_mutex);
|
mutex_lock(&tty_mutex);
|
||||||
mutex_lock(&devpts_mutex);
|
mutex_lock(&devpts_mutex);
|
||||||
tty = tty_init_dev(ptm_driver, index);
|
tty = tty_init_dev(ptm_driver, index);
|
||||||
mutex_unlock(&devpts_mutex);
|
|
||||||
tty_lock();
|
|
||||||
mutex_unlock(&tty_mutex);
|
|
||||||
|
|
||||||
if (IS_ERR(tty)) {
|
if (IS_ERR(tty)) {
|
||||||
retval = PTR_ERR(tty);
|
retval = PTR_ERR(tty);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The tty returned here is locked so we can safely
|
||||||
|
drop the mutex */
|
||||||
|
mutex_unlock(&devpts_mutex);
|
||||||
|
mutex_unlock(&tty_mutex);
|
||||||
|
|
||||||
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
|
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
|
||||||
|
|
||||||
tty_add_file(tty, filp);
|
tty_add_file(tty, filp);
|
||||||
|
@ -654,16 +656,17 @@ static int ptmx_open(struct inode *inode, struct file *filp)
|
||||||
if (retval)
|
if (retval)
|
||||||
goto err_release;
|
goto err_release;
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return 0;
|
return 0;
|
||||||
err_release:
|
err_release:
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
tty_release(inode, filp);
|
tty_release(inode, filp);
|
||||||
return retval;
|
return retval;
|
||||||
out:
|
out:
|
||||||
|
mutex_unlock(&tty_mutex);
|
||||||
devpts_kill_index(inode, index);
|
devpts_kill_index(inode, index);
|
||||||
tty_unlock();
|
|
||||||
err_file:
|
err_file:
|
||||||
|
mutex_unlock(&devpts_mutex);
|
||||||
tty_free_file(filp);
|
tty_free_file(filp);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4052,9 +4052,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
|
||||||
printk("block_til_ready blocking: ttyS%d, count = %d\n",
|
printk("block_til_ready blocking: ttyS%d, count = %d\n",
|
||||||
info->line, info->count);
|
info->line, info->count);
|
||||||
#endif
|
#endif
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
schedule();
|
schedule();
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
remove_wait_queue(&info->open_wait, &wait);
|
remove_wait_queue(&info->open_wait, &wait);
|
||||||
|
|
|
@ -3338,9 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
|
||||||
printk("%s(%d):block_til_ready blocking on %s count=%d\n",
|
printk("%s(%d):block_til_ready blocking on %s count=%d\n",
|
||||||
__FILE__,__LINE__, tty->driver->name, port->count );
|
__FILE__,__LINE__, tty->driver->name, port->count );
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
schedule();
|
schedule();
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
|
|
|
@ -3336,9 +3336,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
|
||||||
}
|
}
|
||||||
|
|
||||||
DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
|
DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
schedule();
|
schedule();
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
|
|
|
@ -3357,9 +3357,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
|
||||||
printk("%s(%d):%s block_til_ready() count=%d\n",
|
printk("%s(%d):%s block_til_ready() count=%d\n",
|
||||||
__FILE__,__LINE__, tty->driver->name, port->count );
|
__FILE__,__LINE__, tty->driver->name, port->count );
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
schedule();
|
schedule();
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
|
|
|
@ -185,6 +185,7 @@ void free_tty_struct(struct tty_struct *tty)
|
||||||
put_device(tty->dev);
|
put_device(tty->dev);
|
||||||
kfree(tty->write_buf);
|
kfree(tty->write_buf);
|
||||||
tty_buffer_free_all(tty);
|
tty_buffer_free_all(tty);
|
||||||
|
tty->magic = 0xDEADDEAD;
|
||||||
kfree(tty);
|
kfree(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,7 +574,7 @@ void __tty_hangup(struct tty_struct *tty)
|
||||||
}
|
}
|
||||||
spin_unlock(&redirect_lock);
|
spin_unlock(&redirect_lock);
|
||||||
|
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
|
|
||||||
/* some functions below drop BTM, so we need this bit */
|
/* some functions below drop BTM, so we need this bit */
|
||||||
set_bit(TTY_HUPPING, &tty->flags);
|
set_bit(TTY_HUPPING, &tty->flags);
|
||||||
|
@ -666,7 +667,7 @@ void __tty_hangup(struct tty_struct *tty)
|
||||||
clear_bit(TTY_HUPPING, &tty->flags);
|
clear_bit(TTY_HUPPING, &tty->flags);
|
||||||
tty_ldisc_enable(tty);
|
tty_ldisc_enable(tty);
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
|
|
||||||
if (f)
|
if (f)
|
||||||
fput(f);
|
fput(f);
|
||||||
|
@ -1103,12 +1104,12 @@ void tty_write_message(struct tty_struct *tty, char *msg)
|
||||||
{
|
{
|
||||||
if (tty) {
|
if (tty) {
|
||||||
mutex_lock(&tty->atomic_write_lock);
|
mutex_lock(&tty->atomic_write_lock);
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
|
if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
tty->ops->write(tty, msg, strlen(msg));
|
tty->ops->write(tty, msg, strlen(msg));
|
||||||
} else
|
} else
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
tty_write_unlock(tty);
|
tty_write_unlock(tty);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -1403,6 +1404,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
|
||||||
}
|
}
|
||||||
initialize_tty_struct(tty, driver, idx);
|
initialize_tty_struct(tty, driver, idx);
|
||||||
|
|
||||||
|
tty_lock(tty);
|
||||||
retval = tty_driver_install_tty(driver, tty);
|
retval = tty_driver_install_tty(driver, tty);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
goto err_deinit_tty;
|
goto err_deinit_tty;
|
||||||
|
@ -1415,9 +1417,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
|
||||||
retval = tty_ldisc_setup(tty, tty->link);
|
retval = tty_ldisc_setup(tty, tty->link);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto err_release_tty;
|
goto err_release_tty;
|
||||||
|
/* Return the tty locked so that it cannot vanish under the caller */
|
||||||
return tty;
|
return tty;
|
||||||
|
|
||||||
err_deinit_tty:
|
err_deinit_tty:
|
||||||
|
tty_unlock(tty);
|
||||||
deinitialize_tty_struct(tty);
|
deinitialize_tty_struct(tty);
|
||||||
free_tty_struct(tty);
|
free_tty_struct(tty);
|
||||||
err_module_put:
|
err_module_put:
|
||||||
|
@ -1426,6 +1430,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
|
||||||
|
|
||||||
/* call the tty release_tty routine to clean out this slot */
|
/* call the tty release_tty routine to clean out this slot */
|
||||||
err_release_tty:
|
err_release_tty:
|
||||||
|
tty_unlock(tty);
|
||||||
printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, "
|
printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, "
|
||||||
"clearing slot %d\n", idx);
|
"clearing slot %d\n", idx);
|
||||||
release_tty(tty, idx);
|
release_tty(tty, idx);
|
||||||
|
@ -1628,7 +1633,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||||
if (tty_paranoia_check(tty, inode, __func__))
|
if (tty_paranoia_check(tty, inode, __func__))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
check_tty_count(tty, __func__);
|
check_tty_count(tty, __func__);
|
||||||
|
|
||||||
__tty_fasync(-1, filp, 0);
|
__tty_fasync(-1, filp, 0);
|
||||||
|
@ -1637,10 +1642,11 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||||
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
|
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
|
||||||
tty->driver->subtype == PTY_TYPE_MASTER);
|
tty->driver->subtype == PTY_TYPE_MASTER);
|
||||||
devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
|
devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
|
||||||
|
/* Review: parallel close */
|
||||||
o_tty = tty->link;
|
o_tty = tty->link;
|
||||||
|
|
||||||
if (tty_release_checks(tty, o_tty, idx)) {
|
if (tty_release_checks(tty, o_tty, idx)) {
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1652,7 +1658,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||||
if (tty->ops->close)
|
if (tty->ops->close)
|
||||||
tty->ops->close(tty, filp);
|
tty->ops->close(tty, filp);
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
/*
|
/*
|
||||||
* Sanity check: if tty->count is going to zero, there shouldn't be
|
* Sanity check: if tty->count is going to zero, there shouldn't be
|
||||||
* any waiters on tty->read_wait or tty->write_wait. We test the
|
* any waiters on tty->read_wait or tty->write_wait. We test the
|
||||||
|
@ -1675,7 +1681,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||||
opens on /dev/tty */
|
opens on /dev/tty */
|
||||||
|
|
||||||
mutex_lock(&tty_mutex);
|
mutex_lock(&tty_mutex);
|
||||||
tty_lock();
|
tty_lock_pair(tty, o_tty);
|
||||||
tty_closing = tty->count <= 1;
|
tty_closing = tty->count <= 1;
|
||||||
o_tty_closing = o_tty &&
|
o_tty_closing = o_tty &&
|
||||||
(o_tty->count <= (pty_master ? 1 : 0));
|
(o_tty->count <= (pty_master ? 1 : 0));
|
||||||
|
@ -1706,7 +1712,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||||
|
|
||||||
printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
|
printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
|
||||||
__func__, tty_name(tty, buf));
|
__func__, tty_name(tty, buf));
|
||||||
tty_unlock();
|
tty_unlock_pair(tty, o_tty);
|
||||||
mutex_unlock(&tty_mutex);
|
mutex_unlock(&tty_mutex);
|
||||||
schedule();
|
schedule();
|
||||||
}
|
}
|
||||||
|
@ -1769,7 +1775,7 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||||
|
|
||||||
/* check whether both sides are closing ... */
|
/* check whether both sides are closing ... */
|
||||||
if (!tty_closing || (o_tty && !o_tty_closing)) {
|
if (!tty_closing || (o_tty && !o_tty_closing)) {
|
||||||
tty_unlock();
|
tty_unlock_pair(tty, o_tty);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1782,14 +1788,16 @@ int tty_release(struct inode *inode, struct file *filp)
|
||||||
tty_ldisc_release(tty, o_tty);
|
tty_ldisc_release(tty, o_tty);
|
||||||
/*
|
/*
|
||||||
* The release_tty function takes care of the details of clearing
|
* The release_tty function takes care of the details of clearing
|
||||||
* the slots and preserving the termios structure.
|
* the slots and preserving the termios structure. The tty_unlock_pair
|
||||||
|
* should be safe as we keep a kref while the tty is locked (so the
|
||||||
|
* unlock never unlocks a freed tty).
|
||||||
*/
|
*/
|
||||||
release_tty(tty, idx);
|
release_tty(tty, idx);
|
||||||
|
tty_unlock_pair(tty, o_tty);
|
||||||
|
|
||||||
/* Make this pty number available for reallocation */
|
/* Make this pty number available for reallocation */
|
||||||
if (devpts)
|
if (devpts)
|
||||||
devpts_kill_index(inode, idx);
|
devpts_kill_index(inode, idx);
|
||||||
tty_unlock();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1893,6 +1901,9 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
|
||||||
* Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev.
|
* Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev.
|
||||||
* tty->count should protect the rest.
|
* tty->count should protect the rest.
|
||||||
* ->siglock protects ->signal/->sighand
|
* ->siglock protects ->signal/->sighand
|
||||||
|
*
|
||||||
|
* Note: the tty_unlock/lock cases without a ref are only safe due to
|
||||||
|
* tty_mutex
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int tty_open(struct inode *inode, struct file *filp)
|
static int tty_open(struct inode *inode, struct file *filp)
|
||||||
|
@ -1916,8 +1927,7 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
mutex_lock(&tty_mutex);
|
mutex_lock(&tty_mutex);
|
||||||
tty_lock();
|
/* This is protected by the tty_mutex */
|
||||||
|
|
||||||
tty = tty_open_current_tty(device, filp);
|
tty = tty_open_current_tty(device, filp);
|
||||||
if (IS_ERR(tty)) {
|
if (IS_ERR(tty)) {
|
||||||
retval = PTR_ERR(tty);
|
retval = PTR_ERR(tty);
|
||||||
|
@ -1938,17 +1948,19 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty) {
|
if (tty) {
|
||||||
|
tty_lock(tty);
|
||||||
retval = tty_reopen(tty);
|
retval = tty_reopen(tty);
|
||||||
if (retval)
|
if (retval < 0) {
|
||||||
|
tty_unlock(tty);
|
||||||
tty = ERR_PTR(retval);
|
tty = ERR_PTR(retval);
|
||||||
} else
|
}
|
||||||
|
} else /* Returns with the tty_lock held for now */
|
||||||
tty = tty_init_dev(driver, index);
|
tty = tty_init_dev(driver, index);
|
||||||
|
|
||||||
mutex_unlock(&tty_mutex);
|
mutex_unlock(&tty_mutex);
|
||||||
if (driver)
|
if (driver)
|
||||||
tty_driver_kref_put(driver);
|
tty_driver_kref_put(driver);
|
||||||
if (IS_ERR(tty)) {
|
if (IS_ERR(tty)) {
|
||||||
tty_unlock();
|
|
||||||
retval = PTR_ERR(tty);
|
retval = PTR_ERR(tty);
|
||||||
goto err_file;
|
goto err_file;
|
||||||
}
|
}
|
||||||
|
@ -1977,7 +1989,7 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||||
printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
|
printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
|
||||||
retval, tty->name);
|
retval, tty->name);
|
||||||
#endif
|
#endif
|
||||||
tty_unlock(); /* need to call tty_release without BTM */
|
tty_unlock(tty); /* need to call tty_release without BTM */
|
||||||
tty_release(inode, filp);
|
tty_release(inode, filp);
|
||||||
if (retval != -ERESTARTSYS)
|
if (retval != -ERESTARTSYS)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -1989,17 +2001,15 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||||
/*
|
/*
|
||||||
* Need to reset f_op in case a hangup happened.
|
* Need to reset f_op in case a hangup happened.
|
||||||
*/
|
*/
|
||||||
tty_lock();
|
|
||||||
if (filp->f_op == &hung_up_tty_fops)
|
if (filp->f_op == &hung_up_tty_fops)
|
||||||
filp->f_op = &tty_fops;
|
filp->f_op = &tty_fops;
|
||||||
tty_unlock();
|
|
||||||
goto retry_open;
|
goto retry_open;
|
||||||
}
|
}
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
|
|
||||||
|
|
||||||
mutex_lock(&tty_mutex);
|
mutex_lock(&tty_mutex);
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
spin_lock_irq(¤t->sighand->siglock);
|
||||||
if (!noctty &&
|
if (!noctty &&
|
||||||
current->signal->leader &&
|
current->signal->leader &&
|
||||||
|
@ -2007,11 +2017,10 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||||
tty->session == NULL)
|
tty->session == NULL)
|
||||||
__proc_set_tty(current, tty);
|
__proc_set_tty(current, tty);
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
mutex_unlock(&tty_mutex);
|
mutex_unlock(&tty_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
err_unlock:
|
err_unlock:
|
||||||
tty_unlock();
|
|
||||||
mutex_unlock(&tty_mutex);
|
mutex_unlock(&tty_mutex);
|
||||||
/* after locks to avoid deadlock */
|
/* after locks to avoid deadlock */
|
||||||
if (!IS_ERR_OR_NULL(driver))
|
if (!IS_ERR_OR_NULL(driver))
|
||||||
|
@ -2094,10 +2103,13 @@ static int __tty_fasync(int fd, struct file *filp, int on)
|
||||||
|
|
||||||
static int tty_fasync(int fd, struct file *filp, int on)
|
static int tty_fasync(int fd, struct file *filp, int on)
|
||||||
{
|
{
|
||||||
|
struct tty_struct *tty = file_tty(filp);
|
||||||
int retval;
|
int retval;
|
||||||
tty_lock();
|
|
||||||
|
tty_lock(tty);
|
||||||
retval = __tty_fasync(fd, filp, on);
|
retval = __tty_fasync(fd, filp, on);
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2934,6 +2946,7 @@ void initialize_tty_struct(struct tty_struct *tty,
|
||||||
tty->pgrp = NULL;
|
tty->pgrp = NULL;
|
||||||
tty->overrun_time = jiffies;
|
tty->overrun_time = jiffies;
|
||||||
tty_buffer_init(tty);
|
tty_buffer_init(tty);
|
||||||
|
mutex_init(&tty->legacy_mutex);
|
||||||
mutex_init(&tty->termios_mutex);
|
mutex_init(&tty->termios_mutex);
|
||||||
mutex_init(&tty->ldisc_mutex);
|
mutex_init(&tty->ldisc_mutex);
|
||||||
init_waitqueue_head(&tty->write_wait);
|
init_waitqueue_head(&tty->write_wait);
|
||||||
|
|
|
@ -567,7 +567,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
||||||
if (IS_ERR(new_ldisc))
|
if (IS_ERR(new_ldisc))
|
||||||
return PTR_ERR(new_ldisc);
|
return PTR_ERR(new_ldisc);
|
||||||
|
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
/*
|
/*
|
||||||
* We need to look at the tty locking here for pty/tty pairs
|
* We need to look at the tty locking here for pty/tty pairs
|
||||||
* when both sides try to change in parallel.
|
* when both sides try to change in parallel.
|
||||||
|
@ -581,12 +581,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (tty->ldisc->ops->num == ldisc) {
|
if (tty->ldisc->ops->num == ldisc) {
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
tty_ldisc_put(new_ldisc);
|
tty_ldisc_put(new_ldisc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
/*
|
/*
|
||||||
* Problem: What do we do if this blocks ?
|
* Problem: What do we do if this blocks ?
|
||||||
* We could deadlock here
|
* We could deadlock here
|
||||||
|
@ -594,7 +594,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
||||||
|
|
||||||
tty_wait_until_sent(tty, 0);
|
tty_wait_until_sent(tty, 0);
|
||||||
|
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
mutex_lock(&tty->ldisc_mutex);
|
mutex_lock(&tty->ldisc_mutex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -604,10 +604,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
||||||
|
|
||||||
while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
|
while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
|
||||||
mutex_unlock(&tty->ldisc_mutex);
|
mutex_unlock(&tty->ldisc_mutex);
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
wait_event(tty_ldisc_wait,
|
wait_event(tty_ldisc_wait,
|
||||||
test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
|
test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
mutex_lock(&tty->ldisc_mutex);
|
mutex_lock(&tty->ldisc_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +622,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
||||||
|
|
||||||
o_ldisc = tty->ldisc;
|
o_ldisc = tty->ldisc;
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
/*
|
/*
|
||||||
* Make sure we don't change while someone holds a
|
* Make sure we don't change while someone holds a
|
||||||
* reference to the line discipline. The TTY_LDISC bit
|
* reference to the line discipline. The TTY_LDISC bit
|
||||||
|
@ -649,7 +649,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
||||||
|
|
||||||
retval = tty_ldisc_wait_idle(tty, 5 * HZ);
|
retval = tty_ldisc_wait_idle(tty, 5 * HZ);
|
||||||
|
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
mutex_lock(&tty->ldisc_mutex);
|
mutex_lock(&tty->ldisc_mutex);
|
||||||
|
|
||||||
/* handle wait idle failure locked */
|
/* handle wait idle failure locked */
|
||||||
|
@ -664,7 +664,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
||||||
clear_bit(TTY_LDISC_CHANGING, &tty->flags);
|
clear_bit(TTY_LDISC_CHANGING, &tty->flags);
|
||||||
mutex_unlock(&tty->ldisc_mutex);
|
mutex_unlock(&tty->ldisc_mutex);
|
||||||
tty_ldisc_put(new_ldisc);
|
tty_ldisc_put(new_ldisc);
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,7 +707,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
||||||
if (o_work)
|
if (o_work)
|
||||||
schedule_work(&o_tty->buf.work);
|
schedule_work(&o_tty->buf.work);
|
||||||
mutex_unlock(&tty->ldisc_mutex);
|
mutex_unlock(&tty->ldisc_mutex);
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,11 +815,11 @@ void tty_ldisc_hangup(struct tty_struct *tty)
|
||||||
* need to wait for another function taking the BTM
|
* need to wait for another function taking the BTM
|
||||||
*/
|
*/
|
||||||
clear_bit(TTY_LDISC, &tty->flags);
|
clear_bit(TTY_LDISC, &tty->flags);
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
cancel_work_sync(&tty->buf.work);
|
cancel_work_sync(&tty->buf.work);
|
||||||
mutex_unlock(&tty->ldisc_mutex);
|
mutex_unlock(&tty->ldisc_mutex);
|
||||||
retry:
|
retry:
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
mutex_lock(&tty->ldisc_mutex);
|
mutex_lock(&tty->ldisc_mutex);
|
||||||
|
|
||||||
/* At this point we have a closed ldisc and we want to
|
/* At this point we have a closed ldisc and we want to
|
||||||
|
@ -830,7 +830,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
|
||||||
if (atomic_read(&tty->ldisc->users) != 1) {
|
if (atomic_read(&tty->ldisc->users) != 1) {
|
||||||
char cur_n[TASK_COMM_LEN], tty_n[64];
|
char cur_n[TASK_COMM_LEN], tty_n[64];
|
||||||
long timeout = 3 * HZ;
|
long timeout = 3 * HZ;
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
|
|
||||||
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
|
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
|
||||||
timeout = MAX_SCHEDULE_TIMEOUT;
|
timeout = MAX_SCHEDULE_TIMEOUT;
|
||||||
|
@ -911,10 +911,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
|
||||||
* race with the set_ldisc code path.
|
* race with the set_ldisc code path.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
tty_ldisc_halt(tty);
|
tty_ldisc_halt(tty);
|
||||||
tty_ldisc_flush_works(tty);
|
tty_ldisc_flush_works(tty);
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
|
|
||||||
mutex_lock(&tty->ldisc_mutex);
|
mutex_lock(&tty->ldisc_mutex);
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -4,29 +4,59 @@
|
||||||
#include <linux/semaphore.h>
|
#include <linux/semaphore.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
|
||||||
/*
|
/* Legacy tty mutex glue */
|
||||||
* The 'big tty mutex'
|
|
||||||
*
|
|
||||||
* This mutex is taken and released by tty_lock() and tty_unlock(),
|
|
||||||
* replacing the older big kernel lock.
|
|
||||||
* It can no longer be taken recursively, and does not get
|
|
||||||
* released implicitly while sleeping.
|
|
||||||
*
|
|
||||||
* Don't use in new code.
|
|
||||||
*/
|
|
||||||
static DEFINE_MUTEX(big_tty_mutex);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Getting the big tty mutex.
|
* Getting the big tty mutex.
|
||||||
*/
|
*/
|
||||||
void __lockfunc tty_lock(void)
|
|
||||||
|
void __lockfunc tty_lock(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
mutex_lock(&big_tty_mutex);
|
if (tty->magic != TTY_MAGIC) {
|
||||||
|
printk(KERN_ERR "L Bad %p\n", tty);
|
||||||
|
WARN_ON(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tty_kref_get(tty);
|
||||||
|
mutex_lock(&tty->legacy_mutex);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_lock);
|
EXPORT_SYMBOL(tty_lock);
|
||||||
|
|
||||||
void __lockfunc tty_unlock(void)
|
void __lockfunc tty_unlock(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
mutex_unlock(&big_tty_mutex);
|
if (tty->magic != TTY_MAGIC) {
|
||||||
|
printk(KERN_ERR "U Bad %p\n", tty);
|
||||||
|
WARN_ON(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mutex_unlock(&tty->legacy_mutex);
|
||||||
|
tty_kref_put(tty);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_unlock);
|
EXPORT_SYMBOL(tty_unlock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Getting the big tty mutex for a pair of ttys with lock ordering
|
||||||
|
* On a non pty/tty pair tty2 can be NULL which is just fine.
|
||||||
|
*/
|
||||||
|
void __lockfunc tty_lock_pair(struct tty_struct *tty,
|
||||||
|
struct tty_struct *tty2)
|
||||||
|
{
|
||||||
|
if (tty < tty2) {
|
||||||
|
tty_lock(tty);
|
||||||
|
tty_lock(tty2);
|
||||||
|
} else {
|
||||||
|
if (tty2 && tty2 != tty)
|
||||||
|
tty_lock(tty2);
|
||||||
|
tty_lock(tty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(tty_lock_pair);
|
||||||
|
|
||||||
|
void __lockfunc tty_unlock_pair(struct tty_struct *tty,
|
||||||
|
struct tty_struct *tty2)
|
||||||
|
{
|
||||||
|
tty_unlock(tty);
|
||||||
|
if (tty2 && tty2 != tty)
|
||||||
|
tty_unlock(tty2);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(tty_unlock_pair);
|
||||||
|
|
|
@ -230,7 +230,7 @@ int tty_port_block_til_ready(struct tty_port *port,
|
||||||
|
|
||||||
/* block if port is in the process of being closed */
|
/* block if port is in the process of being closed */
|
||||||
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
|
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
|
||||||
wait_event_interruptible_tty(port->close_wait,
|
wait_event_interruptible_tty(tty, port->close_wait,
|
||||||
!(port->flags & ASYNC_CLOSING));
|
!(port->flags & ASYNC_CLOSING));
|
||||||
if (port->flags & ASYNC_HUP_NOTIFY)
|
if (port->flags & ASYNC_HUP_NOTIFY)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
@ -296,9 +296,9 @@ int tty_port_block_til_ready(struct tty_port *port,
|
||||||
retval = -ERESTARTSYS;
|
retval = -ERESTARTSYS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
schedule();
|
schedule();
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
finish_wait(&port->open_wait, &wait);
|
finish_wait(&port->open_wait, &wait);
|
||||||
|
|
||||||
|
|
|
@ -268,6 +268,7 @@ struct tty_struct {
|
||||||
struct mutex ldisc_mutex;
|
struct mutex ldisc_mutex;
|
||||||
struct tty_ldisc *ldisc;
|
struct tty_ldisc *ldisc;
|
||||||
|
|
||||||
|
struct mutex legacy_mutex;
|
||||||
struct mutex termios_mutex;
|
struct mutex termios_mutex;
|
||||||
spinlock_t ctrl_lock;
|
spinlock_t ctrl_lock;
|
||||||
/* Termios values are protected by the termios mutex */
|
/* Termios values are protected by the termios mutex */
|
||||||
|
@ -605,8 +606,12 @@ extern long vt_compat_ioctl(struct tty_struct *tty,
|
||||||
|
|
||||||
/* tty_mutex.c */
|
/* tty_mutex.c */
|
||||||
/* functions for preparation of BKL removal */
|
/* functions for preparation of BKL removal */
|
||||||
extern void __lockfunc tty_lock(void) __acquires(tty_lock);
|
extern void __lockfunc tty_lock(struct tty_struct *tty);
|
||||||
extern void __lockfunc tty_unlock(void) __releases(tty_lock);
|
extern void __lockfunc tty_unlock(struct tty_struct *tty);
|
||||||
|
extern void __lockfunc tty_lock_pair(struct tty_struct *tty,
|
||||||
|
struct tty_struct *tty2);
|
||||||
|
extern void __lockfunc tty_unlock_pair(struct tty_struct *tty,
|
||||||
|
struct tty_struct *tty2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* this shall be called only from where BTM is held (like close)
|
* this shall be called only from where BTM is held (like close)
|
||||||
|
@ -621,9 +626,9 @@ extern void __lockfunc tty_unlock(void) __releases(tty_lock);
|
||||||
static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
|
static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
|
||||||
long timeout)
|
long timeout)
|
||||||
{
|
{
|
||||||
tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */
|
tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */
|
||||||
tty_wait_until_sent(tty, timeout);
|
tty_wait_until_sent(tty, timeout);
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -638,16 +643,16 @@ static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
|
||||||
*
|
*
|
||||||
* Do not use in new code.
|
* Do not use in new code.
|
||||||
*/
|
*/
|
||||||
#define wait_event_interruptible_tty(wq, condition) \
|
#define wait_event_interruptible_tty(tty, wq, condition) \
|
||||||
({ \
|
({ \
|
||||||
int __ret = 0; \
|
int __ret = 0; \
|
||||||
if (!(condition)) { \
|
if (!(condition)) { \
|
||||||
__wait_event_interruptible_tty(wq, condition, __ret); \
|
__wait_event_interruptible_tty(tty, wq, condition, __ret); \
|
||||||
} \
|
} \
|
||||||
__ret; \
|
__ret; \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define __wait_event_interruptible_tty(wq, condition, ret) \
|
#define __wait_event_interruptible_tty(tty, wq, condition, ret) \
|
||||||
do { \
|
do { \
|
||||||
DEFINE_WAIT(__wait); \
|
DEFINE_WAIT(__wait); \
|
||||||
\
|
\
|
||||||
|
@ -656,9 +661,9 @@ do { \
|
||||||
if (condition) \
|
if (condition) \
|
||||||
break; \
|
break; \
|
||||||
if (!signal_pending(current)) { \
|
if (!signal_pending(current)) { \
|
||||||
tty_unlock(); \
|
tty_unlock(tty); \
|
||||||
schedule(); \
|
schedule(); \
|
||||||
tty_lock(); \
|
tty_lock(tty); \
|
||||||
continue; \
|
continue; \
|
||||||
} \
|
} \
|
||||||
ret = -ERESTARTSYS; \
|
ret = -ERESTARTSYS; \
|
||||||
|
|
|
@ -710,9 +710,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tty_unlock();
|
tty_unlock(tty);
|
||||||
schedule();
|
schedule();
|
||||||
tty_lock();
|
tty_lock(tty);
|
||||||
}
|
}
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
remove_wait_queue(&dev->wait, &wait);
|
remove_wait_queue(&dev->wait, &wait);
|
||||||
|
|
Loading…
Reference in a new issue