On Thu, Apr 30, 2015 at 11:34:20PM -0400, Cody P Schafer wrote:
> 
> > As I've said already, we *can't* set VMIN and use the kernel's support
> > for this. To do that we would need to open the port without O_NONBLOCK,
> > which would prevent sp_nonblocking_read() and sp_nonblocking_write) from
> > working unless the port was reopened first.
> 
> You're right, it becomes more tricky, and isn't a clear win. I hadn't
> thought about needing to support both.
> 
> Generally, fcntl() could be used to set/clear the O_NONBLOCK flag
> without re-opening (assuming there isn't any race danger here), but
> that's extra work on every read.

We've not yet formally documented anything about the thread-safety of
libserialport functions, but my general feeling is that the policy
should look like this:

- Separate threads handling separate ports is OK.

- Having separate "reader" and "writer" threads for the same port is
  OK - we'll define what that means more specifically but I think the
  concept is fairly obvious. Aside from concurrent read & write
  operations though, nothing should be called concurrently on the same
  port.

With that approach, there's a definite race issue with using fcntl() to
switch between blocking and non-blocking behaviour.

> > So - I could add a function which has the semantics you want, but it
> > would do exactly the same thing as calling sp_wait() followed by
> > sp_nonblocking_read(). It would not actually set VMIN=1. Do you see that
> > as worthwhile?
> 
> I think it's a toss up. It's something I'd commonly use, so I'd
> probably end up with a local impl (which would be similar to an
> internal one) anyhow.

I do see the argument for having a function with the semantics you're
looking for. Let's try to pin down what it would look like so we have a
clear proposal to discuss.

How about this:

  sp_blocking_read_next(struct sp_port *port, void *buf,
                        size_t count, unsigned int timeout_ms)

  Read bytes from the specified serial port, returning as soon any data
  is available.

  Parameters
    port        Pointer to port structure.
    buf         Buffer in which to store the bytes read.
    count       Maximum number of bytes to read. Must not be zero.
    timeout_ms  Timeout in milliseconds, or zero to wait indefinitely.

  Returns
    The number of bytes read, or a negative error code. If the result is
    zero, the timeout was reached before any bytes were available. If
    timeout_ms is zero, the function will always return either at least
    one byte, or a negative error code.

  Warning
    If your program runs on Unix, defines its own signal handlers, and
    needs to abort blocking reads when these are called, then you
    should not use this function. It repeats system calls that return
    with EINTR. To be able to abort a read from a signal handler, you
    should implement your own blocking read using sp_nonblocking_read()
    together with a blocking method that makes sense for your program.
    E.g. you can obtain the file descriptor for an open port using
    sp_get_port_handle() and use this to call select() or pselect(),
    with appropriate arrangements to return if a signal is received.

The implementation would be as follows:

  POSIX:
    select() with the specified timeout_ms, but looped to handle EINTR.
    read() with specified buf and count, nonblocking due to O_NONBLOCK.

  Windows:
    SetCommTimeouts() with:
      ReadIntervalTimeout = MAXDWORD
      ReadTotalTimeoutMultiplier = MAXDWORD
      ReadTotalTimeoutConstant = timeout_ms
    ReadFile() with specified buf and count.

One issue I see with this is how to handle the timeout_ms = 0 case on
Windows. The VMIN=1 like behaviour described in the Remarks section of
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363190%28v=vs.85%29.aspx
explicitly requires that ReadTotalTimeoutConstant be set to a value
greater than 0 but less than MAXDWORD, implying a finite timeout.

I do see a solution, though: if timeout_ms = 0, then set
ReadTotalTimeoutConstant = MAXDWORD - 1. If the ReadFile call does
time out, some 49.7 days later, it can just be repeated.

What do you all think?


Martin

------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud 
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
sigrok-devel mailing list
sigrok-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sigrok-devel

Reply via email to