summaryrefslogtreecommitdiffstats
path: root/sys/kern/tty.c
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2016-01-27 22:48:04 +0000
committermarius <marius@FreeBSD.org>2016-01-27 22:48:04 +0000
commit8a3d40f3e5425c839165d3e5d86dac78fc0b2fa9 (patch)
tree9f35e08c97350406026bf3cc3da682a658e8b035 /sys/kern/tty.c
parent9240aed7779eb28e8b36afbed9b59484fd2c6539 (diff)
downloadFreeBSD-src-8a3d40f3e5425c839165d3e5d86dac78fc0b2fa9.zip
FreeBSD-src-8a3d40f3e5425c839165d3e5d86dac78fc0b2fa9.tar.gz
MFC: r294362, r294414, r294753
- Fix tty_drain() and, thus, TIOCDRAIN of the current tty(4) incarnation to actually wait until the TX FIFOs of UARTs have be drained before returning. This is done by bringing the equivalent of the TS_BUSY flag found in the previous implementation back in an ABI-preserving way. Reported and tested by: Patrick Powell - Make the code consistent with itself style-wise and bring it closer to style(9). - Mark unused arguments as such. - Make the ttystates table const.
Diffstat (limited to 'sys/kern/tty.c')
-rw-r--r--sys/kern/tty.c102
1 files changed, 67 insertions, 35 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index ad5a5d2..86e3a3e 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -132,11 +132,11 @@ tty_drain(struct tty *tp, int leaving)
/* buffer is inaccessible */
return (0);
- while (ttyoutq_bytesused(&tp->t_outq) > 0) {
+ while (ttyoutq_bytesused(&tp->t_outq) > 0 || ttydevsw_busy(tp)) {
ttydevsw_outwakeup(tp);
/* Could be handled synchronously. */
bytesused = ttyoutq_bytesused(&tp->t_outq);
- if (bytesused == 0)
+ if (bytesused == 0 && !ttydevsw_busy(tp))
return (0);
/* Wait for data to be drained. */
@@ -175,6 +175,7 @@ tty_drain(struct tty *tp, int leaving)
static __inline int
ttydev_enter(struct tty *tp)
{
+
tty_lock(tp);
if (tty_gone(tp) || !tty_opened(tp)) {
@@ -189,6 +190,7 @@ ttydev_enter(struct tty *tp)
static void
ttydev_leave(struct tty *tp)
{
+
tty_lock_assert(tp, MA_OWNED);
if (tty_opened(tp) || tp->t_flags & TF_OPENCLOSE) {
@@ -234,7 +236,8 @@ ttydev_leave(struct tty *tp)
* Operations that are exposed through the character device in /dev.
*/
static int
-ttydev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+ttydev_open(struct cdev *dev, int oflags, int devtype __unused,
+ struct thread *td)
{
struct tty *tp;
int error = 0;
@@ -332,7 +335,8 @@ done: tp->t_flags &= ~TF_OPENCLOSE;
}
static int
-ttydev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
+ttydev_close(struct cdev *dev, int fflag, int devtype __unused,
+ struct thread *td __unused)
{
struct tty *tp = dev->si_drv1;
@@ -373,6 +377,7 @@ ttydev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
static __inline int
tty_is_ctty(struct tty *tp, struct proc *p)
{
+
tty_lock_assert(tp, MA_OWNED);
return (p->p_session == tp->t_session && p->p_flag & P_CONTROLT);
@@ -653,7 +658,7 @@ tty_kqops_read_detach(struct knote *kn)
}
static int
-tty_kqops_read_event(struct knote *kn, long hint)
+tty_kqops_read_event(struct knote *kn, long hint __unused)
{
struct tty *tp = kn->kn_hook;
@@ -677,7 +682,7 @@ tty_kqops_write_detach(struct knote *kn)
}
static int
-tty_kqops_write_event(struct knote *kn, long hint)
+tty_kqops_write_event(struct knote *kn, long hint __unused)
{
struct tty *tp = kn->kn_hook;
@@ -697,6 +702,7 @@ static struct filterops tty_kqops_read = {
.f_detach = tty_kqops_read_detach,
.f_event = tty_kqops_read_event,
};
+
static struct filterops tty_kqops_write = {
.f_isfd = 1,
.f_detach = tty_kqops_write_detach,
@@ -752,7 +758,8 @@ static struct cdevsw ttydev_cdevsw = {
*/
static int
-ttyil_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+ttyil_open(struct cdev *dev, int oflags __unused, int devtype __unused,
+ struct thread *td)
{
struct tty *tp;
int error = 0;
@@ -771,14 +778,18 @@ ttyil_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
}
static int
-ttyil_close(struct cdev *dev, int flag, int mode, struct thread *td)
+ttyil_close(struct cdev *dev __unused, int flag __unused, int mode __unused,
+ struct thread *td __unused)
{
+
return (0);
}
static int
-ttyil_rdwr(struct cdev *dev, struct uio *uio, int ioflag)
+ttyil_rdwr(struct cdev *dev __unused, struct uio *uio __unused,
+ int ioflag __unused)
{
+
return (ENODEV);
}
@@ -875,45 +886,49 @@ tty_init_console(struct tty *tp, speed_t s)
*/
static int
-ttydevsw_defopen(struct tty *tp)
+ttydevsw_defopen(struct tty *tp __unused)
{
return (0);
}
static void
-ttydevsw_defclose(struct tty *tp)
+ttydevsw_defclose(struct tty *tp __unused)
{
+
}
static void
-ttydevsw_defoutwakeup(struct tty *tp)
+ttydevsw_defoutwakeup(struct tty *tp __unused)
{
panic("Terminal device has output, while not implemented");
}
static void
-ttydevsw_definwakeup(struct tty *tp)
+ttydevsw_definwakeup(struct tty *tp __unused)
{
+
}
static int
-ttydevsw_defioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
+ttydevsw_defioctl(struct tty *tp __unused, u_long cmd __unused,
+ caddr_t data __unused, struct thread *td __unused)
{
return (ENOIOCTL);
}
static int
-ttydevsw_defcioctl(struct tty *tp, int unit, u_long cmd, caddr_t data, struct thread *td)
+ttydevsw_defcioctl(struct tty *tp __unused, int unit __unused,
+ u_long cmd __unused, caddr_t data __unused, struct thread *td __unused)
{
return (ENOIOCTL);
}
static int
-ttydevsw_defparam(struct tty *tp, struct termios *t)
+ttydevsw_defparam(struct tty *tp __unused, struct termios *t)
{
/*
@@ -935,7 +950,8 @@ ttydevsw_defparam(struct tty *tp, struct termios *t)
}
static int
-ttydevsw_defmodem(struct tty *tp, int sigon, int sigoff)
+ttydevsw_defmodem(struct tty *tp __unused, int sigon __unused,
+ int sigoff __unused)
{
/* Simulate a carrier to make the TTY layer happy. */
@@ -943,25 +959,34 @@ ttydevsw_defmodem(struct tty *tp, int sigon, int sigoff)
}
static int
-ttydevsw_defmmap(struct tty *tp, vm_ooffset_t offset, vm_paddr_t *paddr,
- int nprot, vm_memattr_t *memattr)
+ttydevsw_defmmap(struct tty *tp __unused, vm_ooffset_t offset __unused,
+ vm_paddr_t *paddr __unused, int nprot __unused,
+ vm_memattr_t *memattr __unused)
{
return (-1);
}
static void
-ttydevsw_defpktnotify(struct tty *tp, char event)
+ttydevsw_defpktnotify(struct tty *tp __unused, char event __unused)
{
+
}
static void
-ttydevsw_deffree(void *softc)
+ttydevsw_deffree(void *softc __unused)
{
panic("Terminal device freed without a free-handler");
}
+static bool
+ttydevsw_defbusy(struct tty *tp __unused)
+{
+
+ return (FALSE);
+}
+
/*
* TTY allocation and deallocation. TTY devices can be deallocated when
* the driver doesn't use it anymore, when the TTY isn't a session's
@@ -996,6 +1021,7 @@ tty_alloc_mutex(struct ttydevsw *tsw, void *sc, struct mtx *mutex)
PATCH_FUNC(mmap);
PATCH_FUNC(pktnotify);
PATCH_FUNC(free);
+ PATCH_FUNC(busy);
#undef PATCH_FUNC
tp = malloc(sizeof(struct tty), M_TTY, M_WAITOK|M_ZERO);
@@ -1082,6 +1108,7 @@ tty_rel_free(struct tty *tp)
void
tty_rel_pgrp(struct tty *tp, struct pgrp *pg)
{
+
MPASS(tp->t_sessioncnt > 0);
tty_lock_assert(tp, MA_OWNED);
@@ -1094,6 +1121,7 @@ tty_rel_pgrp(struct tty *tp, struct pgrp *pg)
void
tty_rel_sess(struct tty *tp, struct session *sess)
{
+
MPASS(tp->t_sessioncnt > 0);
/* Current session has left. */
@@ -1108,6 +1136,7 @@ tty_rel_sess(struct tty *tp, struct session *sess)
void
tty_rel_gone(struct tty *tp)
{
+
MPASS(!tty_gone(tp));
/* Simulate carrier removal. */
@@ -1129,6 +1158,7 @@ tty_rel_gone(struct tty *tp)
static void
tty_to_xtty(struct tty *tp, struct xtty *xt)
{
+
tty_lock_assert(tp, MA_OWNED);
xt->xt_size = sizeof(struct xtty);
@@ -1380,6 +1410,7 @@ tty_signal_pgrp(struct tty *tp, int sig)
void
tty_wakeup(struct tty *tp, int flags)
{
+
if (tp->t_flags & TF_ASYNC && tp->t_sigio != NULL)
pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL));
@@ -1442,6 +1473,7 @@ tty_timedwait(struct tty *tp, struct cv *cv, int hz)
void
tty_flush(struct tty *tp, int flags)
{
+
if (flags & FWRITE) {
tp->t_flags &= ~TF_HIWAT_OUT;
ttyoutq_flush(&tp->t_outq);
@@ -1832,10 +1864,11 @@ tty_ioctl(struct tty *tp, u_long cmd, void *data, int fflag, struct thread *td)
dev_t
tty_udev(struct tty *tp)
{
+
if (tp->t_dev)
- return dev2udev(tp->t_dev);
+ return (dev2udev(tp->t_dev));
else
- return NODEV;
+ return (NODEV);
}
int
@@ -1904,8 +1937,8 @@ ttyhook_defrint(struct tty *tp, char c, int flags)
}
int
-ttyhook_register(struct tty **rtp, struct proc *p, int fd,
- struct ttyhook *th, void *softc)
+ttyhook_register(struct tty **rtp, struct proc *p, int fd, struct ttyhook *th,
+ void *softc)
{
struct tty *tp;
struct file *fp;
@@ -2056,7 +2089,7 @@ static struct cdevsw ttyconsdev_cdevsw = {
};
static void
-ttyconsdev_init(void *unused)
+ttyconsdev_init(void *unused __unused)
{
dev_console = make_dev_credf(MAKEDEV_ETERNAL, &ttyconsdev_cdevsw, 0,
@@ -2081,7 +2114,7 @@ ttyconsdev_select(const char *name)
#include <ddb/ddb.h>
#include <ddb/db_sym.h>
-static struct {
+static const struct {
int flag;
char val;
} ttystates[] = {
@@ -2134,6 +2167,7 @@ static struct {
static void
_db_show_devsw(const char *sep, const struct ttydevsw *tsw)
{
+
db_printf("%sdevsw: ", sep);
db_printsym((db_addr_t)tsw, DB_STGY_ANY);
db_printf(" (%p)\n", tsw);
@@ -2148,9 +2182,11 @@ _db_show_devsw(const char *sep, const struct ttydevsw *tsw)
DB_PRINTSYM(pktnotify, tsw->tsw_pktnotify);
DB_PRINTSYM(free, tsw->tsw_free);
}
+
static void
_db_show_hooks(const char *sep, const struct ttyhook *th)
{
+
db_printf("%shook: ", sep);
db_printsym((db_addr_t)th, DB_STGY_ANY);
db_printf(" (%p)\n", th);
@@ -2256,17 +2292,13 @@ DB_SHOW_ALL_COMMAND(ttys, db_show_all_ttys)
isiz = tp->t_inq.ti_nblocks * TTYINQ_DATASIZE;
osiz = tp->t_outq.to_nblocks * TTYOUTQ_DATASIZE;
- db_printf("%p %10s %5zu %4u %4u %4zu %5zu %4u %4zu %5u %5d %5d ",
- tp,
- tty_devname(tp),
- isiz,
+ db_printf("%p %10s %5zu %4u %4u %4zu %5zu %4u %4zu %5u %5d "
+ "%5d ", tp, tty_devname(tp), isiz,
tp->t_inq.ti_linestart - tp->t_inq.ti_begin,
tp->t_inq.ti_end - tp->t_inq.ti_linestart,
- isiz - tp->t_inlow,
- osiz,
+ isiz - tp->t_inlow, osiz,
tp->t_outq.to_end - tp->t_outq.to_begin,
- osiz - tp->t_outlow,
- MIN(tp->t_column, 99999),
+ osiz - tp->t_outlow, MIN(tp->t_column, 99999),
tp->t_session ? tp->t_session->s_sid : 0,
tp->t_pgrp ? tp->t_pgrp->pg_id : 0);
OpenPOWER on IntegriCloud