Date: Wed, 09 Apr 2003 16:23:46 -0700 From: Terry Lambert <tlambert2@mindspring.com> To: Alex Semenyaka <alexs@ratmir.ru> Cc: threads@freebsd.org Subject: Re: termios & non-blocking I/O Message-ID: <3E94AB82.496681D5@mindspring.com> References: <20030408164614.GA7236@comp.chem.msu.su> <20030409044301.J628@gamplex.bde.org> <20030408194944.GA43822@nagual.pp.ru> <20030409112047.GB33265@snark.ratmir.ru> <3E940993.FBAFFD70@mindspring.com> <20030409123431.GD33144@snark.ratmir.ru>
next in thread | previous in thread | raw e-mail | index | archive | help
Alex Semenyaka wrote: > Yes it is permissable, it is just in the disagreement with the behaviour > when MIN>0 and TIME=0. Don't you think the behaviour in the (TIME=0, MIN>0) > and (TIME>0, MIN=0) should be consistent somehow? Consistent with what? The cases are: MIN TIME 1) >0 >0 Interbyte timer; after 1 byte received, timer is started; if MIN bytes received before timer is statisfied, return. If another byte is received, timer is reset; if timer expires, read is satisfied. 2) >0 =0 Pending read is not satisfied until MIN bytes received. 3) =0 >0 NOT interbyte timer; read is satisfied on a single byte received or timer expired. 4) =0 =0 Polling read; available bytes up to number of requested bytes is returned, and read is always satisfied. The specification further indicates that the resolution on the TIME timer is .1 *SECOND*. This basically means that, if it is handled in the kernel, case #1 could *block all other threads indefinitely*, up to .1S * MIN, which for MIN=100, TIME=1 is *10 FULL SECONDS*. That's *obviously* unacceptable. I think it is impossible to implement case #1 correctly with NBIO enabled, and would convert it to case #4, and implement the TIME in user space in libc_r. Case #2 is still not correctly handled at all by your proposed change; libc_r work is required to avoid stalling until input is present; the correct return on NBIO is pretty obviously "EAGAIN,-1"; HOWEVER, you may have received *some* input data, but not MIN worth of input data; returning some number < MIN violates the interface contract; so does losing the data. Case #3 is a full read timer for one byte; also not correctly handled in the face of the proposed change. For a TIME=100, we are talking about stalling all threads for 100 seconds; the correct return is Case #4 is polling I/O; it's trivial to implement in libc_r. I think the big issue here is the "short read" case in #2. The correct thing, to me, would be to return the number of bytes read on the NBIO descriptor, and let the libc_r figure out that that number is less than the number requested. > Then, changing the kernel behavour is simple, straightforward and also > PERFECTLY permissable while tracing the situation with the descriptor mode > in libc_r is not so simple. To be fair such tracing might be a difficult > task. Rule of thumb: If it adds latency, which is always annoying; if it can add an arbitray number of seconds of latency, it's unacceptable. > No, sorry, you have missed my point. Sure I do NOT propose to block > the input when TIME>0. I propose to return -1/EAGAIN (as in the > MIN>0 case) instead of 0 (as it is done now). That is what I called > "the second way". And in this case both libc_r and program can > easely distinct between EOF and nothing-to-read situation and handle > them properly. Also all other threads will not be stucked. The problem with this is case #2 with some number of characters less than MIN. For example, let us propose a MIN of 10, with 3 characters pending input at the time the read is called; you have two cases: #1 TIME>0 I argue that this is impossible to implement in the presence of NBIO, since you can not return both the value of the short read, and the fact that the timer would result in a block, simultaneously. Best approach is to cause an error, EAGAIN,-1. #2 TIME=0 I argue that the value of the short read should be returned, rather than an error. At least in this approach, you can identify in libc_r that a short read has occurred, and that the thread must be rescheduled in order to complete the remaining read, up to MIN. These cases are somewhat contrived, in that use of MIN/TIME values, in other words non-canonical input processing, is at odds with the threads model. At best, combining them provides for the ability to poll (#4: an incredibly bad thing in a threads environment, since a user space scheduler will not necessarily ever schedule another thread to run, if there is a polling thread), and the ability to ask for "X or more characters, up to Y, where MIN=Z and the character count to read(2)=Y" (#2). Probably the only legitimate use in the presence of threads is #2, to get "allowed and expected bounded read lengths", and that's the one you want to change so that it won't work any more. -- Terry
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3E94AB82.496681D5>