=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/tty.c,v retrieving revision 1.265 retrieving revision 1.266 diff -c -r1.265 -r1.266 *** src/usr.bin/tmux/tty.c 2017/04/18 21:41:42 1.265 --- src/usr.bin/tmux/tty.c 2017/04/19 06:52:27 1.266 *************** *** 1,4 **** ! /* $OpenBSD: tty.c,v 1.265 2017/04/18 21:41:42 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: tty.c,v 1.266 2017/04/19 06:52:27 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott *************** *** 79,84 **** --- 79,88 ---- #define tty_pane_full_width(tty, ctx) \ ((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx) + #define TTY_BLOCK_INTERVAL (100000 /* 100 milliseconds */) + #define TTY_BLOCK_START(tty) (1 + ((tty)->sx * (tty)->sy) * 8) + #define TTY_BLOCK_STOP(tty) (1 + ((tty)->sx * (tty)->sy) / 8) + void tty_create_log(void) { *************** *** 172,177 **** --- 176,226 ---- } static void + tty_timer_callback(__unused int fd, __unused short events, void *data) + { + struct tty *tty = data; + struct client *c = tty->client; + struct timeval tv = { .tv_usec = TTY_BLOCK_INTERVAL }; + + log_debug("%s: %zu discarded", c->name, tty->discarded); + + c->flags |= CLIENT_REDRAW; + c->discarded += tty->discarded; + + if (tty->discarded < TTY_BLOCK_STOP(tty)) { + tty->flags &= ~TTY_BLOCK; + tty_invalidate(tty); + return; + } + tty->discarded = 0; + evtimer_add(&tty->timer, &tv); + } + + static int + tty_block_maybe(struct tty *tty) + { + struct client *c = tty->client; + size_t size = EVBUFFER_LENGTH(tty->out); + struct timeval tv = { .tv_usec = TTY_BLOCK_INTERVAL }; + + if (size < TTY_BLOCK_START(tty)) + return (0); + + if (tty->flags & TTY_BLOCK) + return (1); + tty->flags |= TTY_BLOCK; + + log_debug("%s: can't keep up, %zu discarded", c->name, size); + + evbuffer_drain(tty->out, size); + c->discarded += size; + + tty->discarded = 0; + evtimer_add(&tty->timer, &tv); + return (1); + } + + static void tty_write_callback(__unused int fd, __unused short events, void *data) { struct tty *tty = data; *************** *** 184,189 **** --- 233,241 ---- return; log_debug("%s: wrote %d bytes (of %zu)", c->name, nwrite, size); + if (tty_block_maybe(tty)) + return; + if (EVBUFFER_LENGTH(tty->out) != 0) event_add(&tty->event_out, NULL); } *************** *** 198,204 **** } tty->flags |= TTY_OPENED; ! tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE); event_set(&tty->event_in, tty->fd, EV_PERSIST|EV_READ, tty_read_callback, tty); --- 250,256 ---- } tty->flags |= TTY_OPENED; ! tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE|TTY_BLOCK|TTY_TIMER); event_set(&tty->event_in, tty->fd, EV_PERSIST|EV_READ, tty_read_callback, tty); *************** *** 207,212 **** --- 259,266 ---- event_set(&tty->event_out, tty->fd, EV_WRITE, tty_write_callback, tty); tty->out = evbuffer_new(); + evtimer_set(&tty->timer, tty_timer_callback, tty); + tty_start_tty(tty); tty_keys_build(tty); *************** *** 273,278 **** --- 327,335 ---- return; tty->flags &= ~TTY_STARTED; + event_del(&tty->timer); + tty->flags &= ~TTY_BLOCK; + event_del(&tty->event_in); event_del(&tty->event_out); *************** *** 425,433 **** { struct client *c = tty->client; evbuffer_add(tty->out, buf, len); log_debug("%s: %.*s", c->name, (int)len, (const char *)buf); ! tty->written += len; if (tty_log_fd != -1) write(tty_log_fd, buf, len); --- 482,495 ---- { struct client *c = tty->client; + if (tty->flags & TTY_BLOCK) { + tty->discarded += len; + return; + } + evbuffer_add(tty->out, buf, len); log_debug("%s: %.*s", c->name, (int)len, (const char *)buf); ! c->written += len; if (tty_log_fd != -1) write(tty_log_fd, buf, len);