[RTEMS Project] #2176: fishy behavior in termios tx task mode

RTEMS trac trac at rtems.org
Thu Dec 18 12:35:42 UTC 2014


#2176: fishy behavior in termios tx task mode
--------------------+----------------------------
 Reporter:  johill  |       Owner:  joel.sherrill
     Type:  defect  |      Status:  new
 Priority:  low     |   Milestone:  5.0
Component:  cpukit  |     Version:  4.10
 Severity:  normal  |  Resolution:
 Keywords:          |
--------------------+----------------------------
Changes (by sebastian.huber):

 * priority:  normal => low
 * milestone:  4.11 => 5.0


Old description:

> I have a look around in the drivers in the various BSPs and I notice that
> none of the termios drivers appear to transmit characters at task level
> even if they are running in termios task mode. Maybe all (most) of them
> send characters in the ISR. If there was a large frame of characters to
> send then this could lock out task activity for too long.
>
> FWIW, I had a closer look at this today, and maybe something is fishy in
> the termios code when the TX part of termios runs in task driven mode. It
> seems that in task mode if the UART can accept characters immediately in
> the write routine then we wouldn’t need to turn on any interrupts at all.
> The write routine would need to somehow tell termios how many characters
> it sent; presumably this would occur by calling
> rtems_termios_dequeue_characters in the driver's write function. I see in
> the code that this tries to work, rtems_termios_dequeue_characters posts
> the semaphore of termios tx and increases the characters sent count of
> termios. However after the write routine returns it goes badly.
>
> If the transmitter runs in termios TASK mode and the driver's write
> routine does not immediately enable an interrupt, then it returns to the
> code below in rtems_termios_puts and it sets the transmitter to rob_busy.
> After that the termios tx daemon proceeds to step through all of the
> characters remaining (I think that I see this in the debugger) and
> discards them because the transmitter stays in rob_busy state.
>
> It's also probably odd that termios calls the write function with
> interrupts disabled when it is in task driven mode; we could loop
> outputting a large frame of characters in the write routine at task level
> with interrupts globally disabled.
>
>                 if (tty->rawOutBufState == rob_idle) {
>                   /* check, whether XOFF has been received */
>                   if (!(tty->flow_ctrl & FL_ORCVXOF)) {
>                     (*tty->device.write)(tty->minor,
>                         (char
> *)&tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1);
>                   }
>                   else {
>                     /* remember that output has been stopped due to flow
> ctrl*/
>                     tty->flow_ctrl |= FL_OSTOP;
>                   }
>                   tty->rawOutBufState = rob_busy;
>                 }
>
> [debug]#0  rtems_termios_puts (_buf=0x9ca60, len=1, tty=0x11509c) at
> /home/hill/nios2-rtems/rtems/rtems-
> git/rtems-4.10/c/src/../../cpukit/libcsupport/src/termios.c:677
> [debug]#1  0x00015c68 in oproc (c=99 'c', tty=0x11509c) at
> /home/hill/nios2-rtems/rtems/rtems-
> git/rtems-4.10/c/src/../../cpukit/libcsupport/src/termios.c:748
> [debug]#2  0x00015d9c in rtems_termios_write (arg=0x9cad8) at
> /home/hill/nios2-rtems/rtems/rtems-
> git/rtems-4.10/c/src/../../cpukit/libcsupport/src/termios.c:770
> [debug]#3  0x00002ef0 in console_write (major=0, minor=0, arg=0x9cad8) at
> /home/hill/nios2-rtems/rtems/rtems-git/rtems-4.10/c/src/lib/libbsp/nios2
> /altera-sys-config/./console/console.c:171
> [debug]#4  0x0006c328 in rtems_io_write (major=0, minor=0,
> argument=0x9cad8) at /home/hill/nios2-rtems/rtems/rtems-
> git/rtems-4.10/c/src/../../cpukit/sapi/src/iowrite.c:47
> [debug]#5  0x00068044 in device_write (iop=0x114988, buffer=0x3366d4,
> count=44) at /home/hill/nios2-rtems/rtems/rtems-
> git/rtems-4.10/c/src/../../cpukit/libfs/src/imfs/deviceio.c:160
> [debug]#6  0x00017ef4 in write (fd=1, buffer=0x3366d4, count=44) at
> /home/hill/nios2-rtems/rtems/rtems-
> git/rtems-4.10/c/src/../../cpukit/libcsupport/src/write.c:51
> [debug]#7  0x0007f078 in _write_r (ptr=0x9d638, fd=1, buf=0x3366d4,
> nbytes=44) at /home/hill/nios2-rtems/rtems/rtems-
> git/rtems-4.10/c/src/../../cpukit/libcsupport/src/write_r.c:38
> [debug]#8  0x0006d488 in _fflush_r (ptr=0x9d638, fp=0x9d98c) at
> ../../../../../../nios2-rtems/altera/altera11.0/gnu-tools/rtems-
> patched/gcc-4.1/newlib/libc/stdio/fflush.c:214
> [debug]#9  0x000754e8 in __sfvwrite_r (ptr=0x9d638, fp=0x9d98c,
> uio=0x9cbe0) at ../../../../../../nios2-rtems/altera/altera11.0/gnu-tools
> /rtems-patched/gcc-4.1/newlib/libc/stdio/fvwrite.c:257
> [debug]#10 0x0007830c in __sprint_r (ptr=0x9d638, fp=0x20, uio=0x9cbe0)
> at ../../../../../../nios2-rtems/altera/altera11.0/gnu-tools/rtems-
> patched/gcc-4.1/newlib/libc/stdio/vfprintf.c:322
> [debug]#11 0x00072fc8 in _vfprintf_r (data=0x9d638, fp=0x9d98c,
> fmt0=<value optimized out>, ap=0x0) at
> ../../../../../../nios2-rtems/altera/altera11.0/gnu-tools/rtems-
> patched/gcc-4.1/newlib/libc/stdio/vfprintf.c:1501
> [debug]#12 0x0006dce8 in printf (fmt=0x1 "") at
> ../../../../../../nios2-rtems/altera/altera11.0/gnu-tools/rtems-
> patched/gcc-4.1/newlib/libc/stdio/printf.c:52
> [debug]#13 0x00057de0 in bootpc_init (update_files=false, forever=true)
> at /home/hill/nios2-rtems/rtems/rtems-
> git/rtems-4.10/c/src/../../cpukit/libnetworking/nfs/bootp_subr.c:997
> [debug]#14 0x0002960c in rtems_bsdnet_do_bootp () at
> /home/hill/nios2-rtems/rtems/rtems-
> git/rtems-4.10/c/src/../../cpukit/libnetworking/rtems/rtems_bootp.c:23
> [debug]#15 0x0002b218 in rtems_bsdnet_initialize_network () at
> /home/hill/nios2-rtems/rtems/rtems-
> git/rtems-4.10/c/src/../../cpukit/libnetworking/rtems/rtems_glue.c:980
> [debug]#16 0x00001528 in Init (ignored=565432) at init.c:47
> [debug]#17 0x0006ccb0 in _Thread_Handler () at
> /home/hill/nios2-rtems/rtems/rtems-
> git/rtems-4.10/c/src/../../cpukit/score/src/threadhandler.c:145
> [debug]#18 0x0006cc28 in _Thread_Is_heir (the_thread=0x6cc28) at
> ../../cpukit/../../../altera-sys-
> config/lib/include/rtems/score/thread.inl:82
> [debug]Backtrace stopped: frame did not save the PC

New description:

 I have a look around in the drivers in the various BSPs and I notice that
 none of the termios drivers appear to transmit characters at task level
 even if they are running in termios task mode. Maybe all (most) of them
 send characters in the ISR. If there was a large frame of characters to
 send then this could lock out task activity for too long.

 FWIW, I had a closer look at this today, and maybe something is fishy in
 the termios code when the TX part of termios runs in task driven mode. It
 seems that in task mode if the UART can accept characters immediately in
 the write routine then we wouldn’t need to turn on any interrupts at all.
 The write routine would need to somehow tell termios how many characters
 it sent; presumably this would occur by calling
 rtems_termios_dequeue_characters in the driver's write function. I see in
 the code that this tries to work, rtems_termios_dequeue_characters posts
 the semaphore of termios tx and increases the characters sent count of
 termios. However after the write routine returns it goes badly.

 If the transmitter runs in termios TASK mode and the driver's write
 routine does not immediately enable an interrupt, then it returns to the
 code below in rtems_termios_puts and it sets the transmitter to rob_busy.
 After that the termios tx daemon proceeds to step through all of the
 characters remaining (I think that I see this in the debugger) and
 discards them because the transmitter stays in rob_busy state.

 It's also probably odd that termios calls the write function with
 interrupts disabled when it is in task driven mode; we could loop
 outputting a large frame of characters in the write routine at task level
 with interrupts globally disabled.

                 if (tty->rawOutBufState == rob_idle) {
                   /* check, whether XOFF has been received */
                   if (!(tty->flow_ctrl & FL_ORCVXOF)) {
                     (*tty->device.write)(tty->minor,
                         (char
 *)&tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1);
                   }
                   else {
                     /* remember that output has been stopped due to flow
 ctrl*/
                     tty->flow_ctrl |= FL_OSTOP;
                   }
                   tty->rawOutBufState = rob_busy;
                 }

 [debug]#0  rtems_termios_puts (_buf=0x9ca60, len=1, tty=0x11509c) at
 /home/hill/nios2-rtems/rtems/rtems-
 git/rtems-4.10/c/src/../../cpukit/libcsupport/src/termios.c:677
 [debug]#1  0x00015c68 in oproc (c=99 'c', tty=0x11509c) at
 /home/hill/nios2-rtems/rtems/rtems-
 git/rtems-4.10/c/src/../../cpukit/libcsupport/src/termios.c:748
 [debug]#2  0x00015d9c in rtems_termios_write (arg=0x9cad8) at
 /home/hill/nios2-rtems/rtems/rtems-
 git/rtems-4.10/c/src/../../cpukit/libcsupport/src/termios.c:770
 [debug]#3  0x00002ef0 in console_write (major=0, minor=0, arg=0x9cad8) at
 /home/hill/nios2-rtems/rtems/rtems-git/rtems-4.10/c/src/lib/libbsp/nios2
 /altera-sys-config/./console/console.c:171
 [debug]#4  0x0006c328 in rtems_io_write (major=0, minor=0,
 argument=0x9cad8) at /home/hill/nios2-rtems/rtems/rtems-
 git/rtems-4.10/c/src/../../cpukit/sapi/src/iowrite.c:47
 [debug]#5  0x00068044 in device_write (iop=0x114988, buffer=0x3366d4,
 count=44) at /home/hill/nios2-rtems/rtems/rtems-
 git/rtems-4.10/c/src/../../cpukit/libfs/src/imfs/deviceio.c:160
 [debug]#6  0x00017ef4 in write (fd=1, buffer=0x3366d4, count=44) at
 /home/hill/nios2-rtems/rtems/rtems-
 git/rtems-4.10/c/src/../../cpukit/libcsupport/src/write.c:51
 [debug]#7  0x0007f078 in _write_r (ptr=0x9d638, fd=1, buf=0x3366d4,
 nbytes=44) at /home/hill/nios2-rtems/rtems/rtems-
 git/rtems-4.10/c/src/../../cpukit/libcsupport/src/write_r.c:38
 [debug]#8  0x0006d488 in _fflush_r (ptr=0x9d638, fp=0x9d98c) at
 ../../../../../../nios2-rtems/altera/altera11.0/gnu-tools/rtems-
 patched/gcc-4.1/newlib/libc/stdio/fflush.c:214
 [debug]#9  0x000754e8 in __sfvwrite_r (ptr=0x9d638, fp=0x9d98c,
 uio=0x9cbe0) at ../../../../../../nios2-rtems/altera/altera11.0/gnu-tools
 /rtems-patched/gcc-4.1/newlib/libc/stdio/fvwrite.c:257
 [debug]#10 0x0007830c in __sprint_r (ptr=0x9d638, fp=0x20, uio=0x9cbe0) at
 ../../../../../../nios2-rtems/altera/altera11.0/gnu-tools/rtems-
 patched/gcc-4.1/newlib/libc/stdio/vfprintf.c:322
 [debug]#11 0x00072fc8 in _vfprintf_r (data=0x9d638, fp=0x9d98c,
 fmt0=<value optimized out>, ap=0x0) at
 ../../../../../../nios2-rtems/altera/altera11.0/gnu-tools/rtems-
 patched/gcc-4.1/newlib/libc/stdio/vfprintf.c:1501
 [debug]#12 0x0006dce8 in printf (fmt=0x1 "") at
 ../../../../../../nios2-rtems/altera/altera11.0/gnu-tools/rtems-
 patched/gcc-4.1/newlib/libc/stdio/printf.c:52
 [debug]#13 0x00057de0 in bootpc_init (update_files=false, forever=true) at
 /home/hill/nios2-rtems/rtems/rtems-
 git/rtems-4.10/c/src/../../cpukit/libnetworking/nfs/bootp_subr.c:997
 [debug]#14 0x0002960c in rtems_bsdnet_do_bootp () at
 /home/hill/nios2-rtems/rtems/rtems-
 git/rtems-4.10/c/src/../../cpukit/libnetworking/rtems/rtems_bootp.c:23
 [debug]#15 0x0002b218 in rtems_bsdnet_initialize_network () at
 /home/hill/nios2-rtems/rtems/rtems-
 git/rtems-4.10/c/src/../../cpukit/libnetworking/rtems/rtems_glue.c:980
 [debug]#16 0x00001528 in Init (ignored=565432) at init.c:47
 [debug]#17 0x0006ccb0 in _Thread_Handler () at
 /home/hill/nios2-rtems/rtems/rtems-
 git/rtems-4.10/c/src/../../cpukit/score/src/threadhandler.c:145
 [debug]#18 0x0006cc28 in _Thread_Is_heir (the_thread=0x6cc28) at
 ../../cpukit/../../../altera-sys-
 config/lib/include/rtems/score/thread.inl:82
 [debug]Backtrace stopped: frame did not save the PC

--

--
Ticket URL: <http://devel.rtems.org/ticket/2176#comment:2>
RTEMS Project <http://www.rtems.org/>
RTEMS Project


More information about the bugs mailing list