(void)sio_getreg(com, com_data);
}
if (fn == 256) {
- kprintf("sio%d: can't drain, serial port might "
- "not exist, disabling\n", device_get_unit(dev));
com_unlock();
lwkt_reltoken(&tty_token);
+ kprintf("sio%d: can't drain, serial port might "
+ "not exist, disabling\n", device_get_unit(dev));
return (ENXIO);
}
} else
com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
if (siosetwater(com, com->it_in.c_ispeed) != 0) {
- com_unlock();
/*
* Leave i/o resources allocated if this is a `cn'-level
* console, so that other devices can't snarf them.
lwkt_reltoken(&tty_token);
return (ENOMEM);
}
- com_unlock();
termioschars(&com->it_in);
com->it_out = com->it_in;
}
/*
- * NOTE: Must be called with tty_token held
+ * NOTE: Normally called with tty_token held but might not be when
+ * operating as the console.
+ *
+ * Must be called with com_lock
*/
static void
sioinput(struct com_s *com)
int recv_data;
struct tty *tp;
- ASSERT_LWKT_TOKEN_HELD(&tty_token);
buf = com->ibuf;
tp = com->tp;
if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) {
lwkt_reltoken(&tty_token);
}
+/*
+ * Called with tty_token held and com_lock held.
+ */
static void
siointr1(struct com_s *com)
{
u_char int_ctl_new;
u_int count;
- lwkt_gettoken(&tty_token);
int_ctl = inb(com->intr_ctl_port);
int_ctl_new = int_ctl;
if (recv_data == KEY_TILDE)
brk_state2 = recv_data;
else if (brk_state2 == KEY_TILDE && recv_data == KEY_CRTLB) {
+ com_unlock();
breakpoint();
+ com_lock();
brk_state1 = brk_state2 = 0;
goto cont;
} else
if (line_status & LSR_BI) {
#if defined(DDB) && defined(BREAK_TO_DEBUGGER)
if (com->unit == comconsole) {
+ com_unlock();
breakpoint();
+ com_lock();
goto cont;
}
#endif
if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND)
#endif /* COM_MULTIPORT */
{
- lwkt_reltoken(&tty_token);
return;
}
}
- lwkt_reltoken(&tty_token);
}
static int
lwkt_reltoken(&tty_token);
}
+/*
+ * Called with tty_token held but no com_lock
+ */
static int
comparam(struct tty *tp, struct termios *t)
{
u_char dlbl;
int unit;
- lwkt_gettoken(&tty_token);
unit = DEV_TO_UNIT(tp->t_dev);
com = com_addr(unit);
if (com == NULL) {
- lwkt_reltoken(&tty_token);
return (ENODEV);
}
if (t->c_ospeed == 0)
divisor = 0;
else {
- if (t->c_ispeed != t->c_ospeed) {
- lwkt_reltoken(&tty_token);
+ if (t->c_ispeed != t->c_ospeed)
return (EINVAL);
- }
divisor = siodivisor(com->rclk, t->c_ispeed);
- if (divisor == 0) {
- lwkt_reltoken(&tty_token);
+ if (divisor == 0)
return (EINVAL);
- }
}
/* parameters are OK, convert them to the com struct and the device */
* unconditionally, but that defeated the careful discarding of
* stale input in sioopen().
*/
- if (com->state >= (CS_BUSY | CS_TTGO))
+ if (com->state >= (CS_BUSY | CS_TTGO)) {
+ com_lock();
siointr1(com);
-
- com_unlock();
+ com_unlock();
+ }
crit_exit();
comstart(tp);
if (com->ibufold != NULL) {
kfree(com->ibufold, M_DEVBUF);
com->ibufold = NULL;
}
- lwkt_reltoken(&tty_token);
return (0);
}
+/*
+ * called with tty_token held
+ */
static int
siosetwater(struct com_s *com, speed_t speed)
{
int ibufsize;
struct tty *tp;
- lwkt_gettoken(&tty_token);
/*
* Make the buffer size large enough to handle a softtty interrupt
* latency of about 2 ticks without loss of throughput or data
cp4ticks = speed / 10 / hz * 4;
for (ibufsize = 128; ibufsize < cp4ticks;)
ibufsize <<= 1;
- if (ibufsize == com->ibufsize) {
- com_lock();
- lwkt_reltoken(&tty_token);
+ if (ibufsize == com->ibufsize)
return (0);
- }
/*
* Allocate input buffer. The extra factor of 2 in the size is
}
/*
- * Read current input buffer, if any. Continue with interrupts
- * disabled.
+ * Read current input buffer.
*/
com_lock();
if (com->iptr != com->ibuf)
com->ibufend = ibuf + ibufsize;
com->ierroff = ibufsize;
com->ihighwater = ibuf + 3 * ibufsize / 4;
- lwkt_reltoken(&tty_token);
+ com_unlock();
return (0);
}
int dwidth, upper;
char padc;
int retval = 0, stop = 0;
- int not_panic_cpu = (panic_cpu_gd != mycpu);
+ int usespin;
+
+ /*
+ * Make a supreme effort to avoid reentrant panics or deadlocks.
+ */
+ if (func == kputchar) {
+ if (mycpu->gd_flags & GDF_KPRINTF)
+ return(0);
+ atomic_set_long(&mycpu->gd_flags, GDF_KPRINTF);
+ }
num = 0;
if (!func)
if (radix < 2 || radix > 36)
radix = 10;
- if (not_panic_cpu && func == kputchar) {
+ usespin = (panic_cpu_gd != mycpu &&
+ func == kputchar &&
+ (((struct putchar_arg *)arg)->flags & TOTTY) == 0);
+ if (usespin) {
crit_enter_hard();
spin_lock_wr(&cons_spin);
}
}
}
done:
- if (not_panic_cpu && func == kputchar) {
+ /*
+ * Cleanup reentrancy issues.
+ */
+ if (func == kputchar)
+ atomic_clear_long(&mycpu->gd_flags, GDF_KPRINTF);
+ if (usespin) {
spin_unlock_wr(&cons_spin);
crit_exit_hard();
}
#undef PCHAR
/*
- * Called from the panic code
+ * Called from the panic code to try to get the console working
+ * again in case we paniced inside a kprintf().
*/
void
kvcreinitspin(void)
{
spin_init(&cons_spin);
+ atomic_clear_long(&mycpu->gd_flags, GDF_KPRINTF);
}