2001-07-03 08:27:12

by James R Bruce

[permalink] [raw]
Subject: serial port O_SYNC functionality in 2.4.5


As far as I can tell from observed operation and from perusing the
code, O_SYNC doesn't seem to be supported by the serial driver in
2.4.5. Writes are forced as far as the serial.c's circular queue, but
O_SYNC seems to be ignored from there on, so any application trying to
do small synchronous writes to the serial port will end up backing it
up PAGE_SIZE bytes rather than getting synchronous operation (which is
incidentally what I was trying to do when I ran into this :).

I'm unfamiliar with the serial driver so I'm not sure the right way to
fix it is, but perhaps using a smaller value for WAKEUP_CHARS from
drivers/char/serial.c when the port is opened with O_SYNC
functionality might do the trick (i.e. 0 rather than 256).

Hopefully someone familiar with that part of the code please can tell
me what should be done... or if a patch or configuration option can
already get that functionality in another way.

Thanks,
Jim Bruce


2001-07-03 20:05:47

by James R Bruce

[permalink] [raw]
Subject: Re: serial port O_SYNC functionality in 2.4.5


Re: serial port O_SYNC func.. by "Stuart MacDonald"@conne
> From: "James R Bruce" <[email protected]>
> > As far as I can tell from observed operation and from perusing the
> > code, O_SYNC doesn't seem to be supported by the serial driver in
> > 2.4.5. Writes are forced as far as the serial.c's circular queue, but
> > O_SYNC seems to be ignored from there on, so any application trying to
> > do small synchronous writes to the serial port will end up backing it
> > up PAGE_SIZE bytes rather than getting synchronous operation (which is
> > incidentally what I was trying to do when I ran into this :).
> >
> > I'm unfamiliar with the serial driver so I'm not sure the right way to
> > fix it is, but perhaps using a smaller value for WAKEUP_CHARS from
> > drivers/char/serial.c when the port is opened with O_SYNC
> > functionality might do the trick (i.e. 0 rather than 256).
>
> That might help, but it might not. That will only make sure that the
> tx circular buffer is empty before getting another byte from the tty
> layer into the buffer.

The overall size of the circular buffer would have to be decreased
too, but that's more of a hack to fix it now; Which I guess is what it
comes to.

> I think you will find that the real problem is that bytes written
> into the hardware go into the fifo, and there's no general way to
> tell when a byte has be actually txed; not in regular operation.

This is not really a problem; 16 bytes of hardware buffering I can
live with; at 19200 baud this is 7ms of lag. The 4096 byte software
buffer causes 1706ms of lag; That *is* a problem. It's a bit like the
difference between a hard disk drive's local buffer and the OS's (much
larger) buffering. O_SYNC on a disk garuntees that the output has
been flushed to the disk, but maybe not the physical medium. On a
serial port, similar functionality would be to have output to pushed
to the UART, but maybe not yet over the actual port.

> You want to run the port in polled mode, which ensures one byte is
> txed/rxed at a time. It's slow and cpu intensive though. setserial's
> man page might have some info on this, also known as "low latency";
> meaning a specific byte has a low period of time between being rxed
> and read/written and txed.

The manpage seems to imply this would work, but it doesn't seem to
affect the software buffering at all (I tried this yesterday). AFAICT
from looking at the driver, the low_latency mode only applies to
reading, not writing: tty_flip_buffer_push(tty) is the only place the
latency flag is ever checked, and that is only called in receive_chars
in serial.c. The application that caused this doesn't get any serial
input whatsoever, so that won't (or at least shouldn't) get called.

I changed WAKEUP_CHARS to 1 rather than 256 (0 would cause processes
to hang forever, btw), and SERIAL_XMIT_SIZE to 16 rather than
PAGE_SIZE. A proper solution would make this conditional on O_SYNC or
low_latency or even a kernel option. Suggestions?

- Jim Bruce

2001-07-03 20:39:12

by Stuart MacDonald

[permalink] [raw]
Subject: Re: serial port O_SYNC functionality in 2.4.5

From: "James R Bruce" <[email protected]>
> The overall size of the circular buffer would have to be decreased
> too, but that's more of a hack to fix it now; Which I guess is what it
> comes to.

I see what you're saying; AFAIUnderstand, the low latency patches
bypass the circular buffer. Or make it size one.

> This is not really a problem; 16 bytes of hardware buffering I can
> live with; at 19200 baud this is 7ms of lag. The 4096 byte software
> buffer causes 1706ms of lag; That *is* a problem. It's a bit like the
> difference between a hard disk drive's local buffer and the OS's (much
> larger) buffering. O_SYNC on a disk garuntees that the output has
> been flushed to the disk, but maybe not the physical medium. On a
> serial port, similar functionality would be to have output to pushed
> to the UART, but maybe not yet over the actual port.

Gotchya.

> The manpage seems to imply this would work, but it doesn't seem to
> affect the software buffering at all (I tried this yesterday). AFAICT
> from looking at the driver, the low_latency mode only applies to
> reading, not writing: tty_flip_buffer_push(tty) is the only place the
> latency flag is ever checked, and that is only called in receive_chars
> in serial.c. The application that caused this doesn't get any serial
> input whatsoever, so that won't (or at least shouldn't) get called.

Hm. I haven't looked at the low_latency stuff, I was just repeating what
I'd heard...

> I changed WAKEUP_CHARS to 1 rather than 256 (0 would cause processes
> to hang forever, btw), and SERIAL_XMIT_SIZE to 16 rather than
> PAGE_SIZE. A proper solution would make this conditional on O_SYNC or
> low_latency or even a kernel option. Suggestions?

If you check the code, the circ buffer will never have a count < 0, so the
hang
is predictible; tty is never called for more tx chars.

I'd say it should be part of low_latency. Although it's probably best to
have
rx low_latency and tx low_latency separately configurable. Honouring O_SYNC
might not be a bad idea as well.

Whatever option probably should make SERIAL_XMIT_SIZE == WAKEUP_CHARS;
SERIAL needs to be a power of two, so 2, 4, 8 or 16 would be good choices.
Probably should be similar to the rx low_latency.

Best way to get this in the serial driver is to do some patches for it
and send them to Ted. :-)

..Stu


2001-07-03 21:09:53

by Russell King

[permalink] [raw]
Subject: Re: serial port O_SYNC functionality in 2.4.5

On Tue, Jul 03, 2001 at 04:42:00PM -0400, Stuart MacDonald wrote:
> Best way to get this in the serial driver is to do some patches for it
> and send them to Ted. :-)

Please copy them to me as well. The ARM tree has a core uart driver
in currently which handles several different types of serial ports.

Thanks.

--
Russell King ([email protected]) The developer of ARM Linux
http://www.arm.linux.org.uk/personal/aboutme.html