From 0e8d20555966942f79e0e8ec29ff2104fda1b646 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 23 Feb 2017 10:06:52 +0100 Subject: termios: Protect raw input buffer with device lock Use the device lock to protect the raw input buffer management, e.g. tail, head and buffer content updates. Update #2914. --- cpukit/libcsupport/src/termios.c | 52 +++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 16 deletions(-) (limited to 'cpukit') diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c index 54b0121aee..1a7562e93c 100644 --- a/cpukit/libcsupport/src/termios.c +++ b/cpukit/libcsupport/src/termios.c @@ -1457,14 +1457,19 @@ fillBufferPoll (struct rtems_termios_tty *tty) static void fillBufferQueue (struct rtems_termios_tty *tty) { + rtems_termios_device_context *ctx = tty->device_context; rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout; - rtems_status_code sc; - int wait = 1; + bool wait = true; while ( wait ) { + rtems_interrupt_lock_context lock_context; + /* * Process characters read from raw queue */ + + rtems_termios_device_lock_acquire (ctx, &lock_context); + while ((tty->rawInBuf.Head != tty->rawInBuf.Tail) && (tty->ccount < (CBUFSIZE-1))) { unsigned char c; @@ -1473,6 +1478,7 @@ fillBufferQueue (struct rtems_termios_tty *tty) newHead = (tty->rawInBuf.Head + 1) % tty->rawInBuf.Size; c = tty->rawInBuf.theBuf[newHead]; tty->rawInBuf.Head = newHead; + if(((tty->rawInBuf.Tail-newHead+tty->rawInBuf.Size) % tty->rawInBuf.Size) < tty->lowwater) { @@ -1494,22 +1500,30 @@ fillBufferQueue (struct rtems_termios_tty *tty) } } + rtems_termios_device_lock_release (ctx, &lock_context); + /* continue processing new character */ if (tty->termios.c_lflag & ICANON) { if (siproc (c, tty)) - wait = 0; + wait = false; } else { siproc (c, tty); if (tty->ccount >= tty->termios.c_cc[VMIN]) - wait = 0; + wait = false; } timeout = tty->rawInBufSemaphoreTimeout; + + rtems_termios_device_lock_acquire (ctx, &lock_context); } + rtems_termios_device_lock_release (ctx, &lock_context); + /* * Wait for characters */ if ( wait ) { + rtems_status_code sc; + sc = rtems_semaphore_obtain( tty->rawInBuf.Semaphore, tty->rawInBufSemaphoreOptions, timeout); if (sc != RTEMS_SUCCESSFUL) @@ -1579,7 +1593,6 @@ int rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len) { struct rtems_termios_tty *tty = ttyp; - unsigned int newTail; char c; int dropped = 0; bool flow_rcv = false; /* true, if flow control char received */ @@ -1644,12 +1657,19 @@ rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len) rtems_termios_device_lock_release (ctx, &lock_context); } } else { - newTail = (tty->rawInBuf.Tail + 1) % tty->rawInBuf.Size; - /* if chars_in_buffer > highwater */ + unsigned int head; + unsigned int oldTail; + unsigned int newTail; + rtems_termios_device_lock_acquire (ctx, &lock_context); - if ((((newTail - tty->rawInBuf.Head + tty->rawInBuf.Size) - % tty->rawInBuf.Size) > tty->highwater) && - !(tty->flow_ctrl & FL_IREQXOF)) { + + head = tty->rawInBuf.Head; + oldTail = tty->rawInBuf.Tail; + newTail = (oldTail + 1) % tty->rawInBuf.Size; + + /* if chars_in_buffer > highwater */ + if ((tty->flow_ctrl & FL_IREQXOF) != 0 && (((newTail - head + + tty->rawInBuf.Size) % tty->rawInBuf.Size) > tty->highwater)) { /* incoming data stream should be stopped */ tty->flow_ctrl |= FL_IREQXOF; if ((tty->flow_ctrl & (FL_MDXOF | FL_ISNTXOF)) @@ -1671,15 +1691,12 @@ rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len) } } - /* reenable interrupts */ - rtems_termios_device_lock_release (ctx, &lock_context); - - if (newTail == tty->rawInBuf.Head) { - dropped++; - } else { + if (newTail != head) { tty->rawInBuf.theBuf[newTail] = c; tty->rawInBuf.Tail = newTail; + rtems_termios_device_lock_release (ctx, &lock_context); + /* * check to see if rcv wakeup callback was set */ @@ -1687,6 +1704,9 @@ rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len) (*tty->tty_rcv.sw_pfn)(&tty->termios, tty->tty_rcv.sw_arg); tty->tty_rcvwakeup = 1; } + } else { + ++dropped; + rtems_termios_device_lock_release (ctx, &lock_context); } } } -- cgit v1.2.3