=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/window.c,v retrieving revision 1.130 retrieving revision 1.131 diff -u -r1.130 -r1.131 --- src/usr.bin/tmux/window.c 2015/05/11 10:10:16 1.130 +++ src/usr.bin/tmux/window.c 2015/05/12 22:40:38 1.131 @@ -1,4 +1,4 @@ -/* $OpenBSD: window.c,v 1.130 2015/05/11 10:10:16 nicm Exp $ */ +/* $OpenBSD: window.c,v 1.131 2015/05/12 22:40:38 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -58,6 +58,7 @@ u_int next_window_id; u_int next_active_point; +void window_pane_timer_callback(int, short, void *); void window_pane_read_callback(struct bufferevent *, void *); void window_pane_error_callback(struct bufferevent *, short, void *); @@ -740,6 +741,9 @@ { window_pane_reset_mode(wp); + if (event_initialized(&wp->timer)) + evtimer_del(&wp->timer); + if (wp->fd != -1) { bufferevent_free(wp->event); close(wp->fd); @@ -867,6 +871,8 @@ wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL, window_pane_error_callback, wp); + + bufferevent_setwatermark(wp->event, EV_READ, 0, READ_SIZE); bufferevent_enable(wp->event, EV_READ|EV_WRITE); free(cmd); @@ -874,21 +880,44 @@ } void +window_pane_timer_callback(unused int fd, unused short events, void *data) +{ + window_pane_read_callback(NULL, data); +} + +void window_pane_read_callback(unused struct bufferevent *bufev, void *data) { - struct window_pane *wp = data; - char *new_data; - size_t new_size; + struct window_pane *wp = data; + struct evbuffer *evb = wp->event->input; + char *new_data; + size_t new_size, available; + struct client *c; + struct timeval tv; - new_size = EVBUFFER_LENGTH(wp->event->input) - wp->pipe_off; + if (event_initialized(&wp->timer)) + evtimer_del(&wp->timer); + + log_debug("%%%u has %zu bytes", wp->id, EVBUFFER_LENGTH(evb)); + + TAILQ_FOREACH(c, &clients, entry) { + if (!tty_client_ready(c, wp)) + continue; + + available = EVBUFFER_LENGTH(c->tty.event->output); + if (available > READ_BACKOFF) + goto start_timer; + } + + new_size = EVBUFFER_LENGTH(evb) - wp->pipe_off; if (wp->pipe_fd != -1 && new_size > 0) { - new_data = EVBUFFER_DATA(wp->event->input); + new_data = EVBUFFER_DATA(evb); bufferevent_write(wp->pipe_event, new_data, new_size); } input_parse(wp); - wp->pipe_off = EVBUFFER_LENGTH(wp->event->input); + wp->pipe_off = EVBUFFER_LENGTH(evb); /* * If we get here, we're not outputting anymore, so set the silence @@ -897,11 +926,22 @@ wp->window->flags |= WINDOW_SILENCE; if (gettimeofday(&wp->window->silence_timer, NULL) != 0) fatal("gettimeofday failed."); + return; + +start_timer: + log_debug("%%%u backing off (%s %zu > %d)", wp->id, c->ttyname, + available, READ_BACKOFF); + + tv.tv_sec = 0; + tv.tv_usec = READ_TIME; + + evtimer_set(&wp->timer, window_pane_timer_callback, wp); + evtimer_add(&wp->timer, &tv); } void -window_pane_error_callback( - unused struct bufferevent *bufev, unused short what, void *data) +window_pane_error_callback(unused struct bufferevent *bufev, unused short what, + void *data) { struct window_pane *wp = data;