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