On Fri, May 1, 2015 at 7:35 AM, Martin Ling <martin-sig...@earth.li> wrote:
> 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.

Well, we could go even more crazy and use dup()/dup2()/dup3() and
carry around 2 file descriptors to the same file (serial port, in our
case): one blocking, one non-blocking.
But that feels a bit extreme.

>> > 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?

It sounds fine to me.

I suppose using OS specific impls rather than using libserialport's
generic event infra is to avoid the bit of overhead with using the
event infra?

------------------------------------------------------------------------------
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