| 220 | } |
| 221 | |
| 222 | static int |
| 223 | ttydisc_read_raw_read_timer(struct tty *tp, struct uio *uio, int ioflag, |
| 224 | int oresid) |
| 225 | { |
| 226 | size_t vmin = MAX(tp->t_termios.c_cc[VMIN], 1); |
| 227 | unsigned int vtime = tp->t_termios.c_cc[VTIME]; |
| 228 | struct timeval end, now, left; |
| 229 | int error, hz; |
| 230 | |
| 231 | MPASS(tp->t_termios.c_cc[VTIME] != 0); |
| 232 | |
| 233 | /* Determine when the read should be expired. */ |
| 234 | end.tv_sec = vtime / 10; |
| 235 | end.tv_usec = (vtime % 10) * 100000; |
| 236 | getmicrotime(&now); |
| 237 | timevaladd(&end, &now); |
| 238 | |
| 239 | for (;;) { |
| 240 | error = tty_wait_background(tp, curthread, SIGTTIN); |
| 241 | if (error) |
| 242 | return (error); |
| 243 | |
| 244 | error = ttyinq_read_uio(&tp->t_inq, tp, uio, |
| 245 | uio->uio_resid, 0); |
| 246 | if (error) |
| 247 | return (error); |
| 248 | if (uio->uio_resid == 0 || (oresid - uio->uio_resid) >= vmin) |
| 249 | return (0); |
| 250 | |
| 251 | /* Calculate how long we should wait. */ |
| 252 | getmicrotime(&now); |
| 253 | if (timevalcmp(&now, &end, >)) |
| 254 | return (0); |
| 255 | left = end; |
| 256 | timevalsub(&left, &now); |
| 257 | hz = tvtohz(&left); |
| 258 | |
| 259 | /* |
| 260 | * We have to wait for more. If the timer expires, we |
| 261 | * should return a 0-byte read. |
| 262 | */ |
| 263 | if (tp->t_flags & TF_ZOMBIE) |
| 264 | return (0); |
| 265 | else if (ioflag & IO_NDELAY) |
| 266 | return (EWOULDBLOCK); |
| 267 | |
| 268 | error = tty_timedwait(tp, &tp->t_inwait, hz); |
| 269 | if (error) |
| 270 | return (error == EWOULDBLOCK ? 0 : error); |
| 271 | } |
| 272 | |
| 273 | return (0); |
| 274 | } |
| 275 | |
| 276 | static int |
| 277 | ttydisc_read_raw_interbyte_timer(struct tty *tp, struct uio *uio, int ioflag) |
no test coverage detected