Data were pushed during the main red worker loop. However there was no garantiee that there was some activities that make the loop do another iteration. This could cause in some condition the loop to stop till a new event was sent. Events were: - data from dispatcher (including wake up from guest); - data from clients; - timeouts on stream; - other timeouts; - polling. So usually polling or wake ups from guest could wake up the loop. This patch wants to add event to trigger when we can write data to clients. This has some advantages: - could lower latency as we don't have to wait a polling timeout (from my experiments using a tight loop so not really the ideal condition to see the improvements the total time was reduced by 2-3%); - help reducing the possibility of hanging loops; - avoid having to scan all clients to detect which one can accept data. Signed-by: Frediano Ziglio <figlio@xxxxxxxxxx> --- server/red-channel.c | 25 ++++++++++++++++--------- server/red-worker.c | 13 ------------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/server/red-channel.c b/server/red-channel.c index fd41493..632007e 100644 --- a/server/red-channel.c +++ b/server/red-channel.c @@ -1345,6 +1345,11 @@ void red_channel_client_push(RedChannelClient *rcc) while ((pipe_item = red_channel_client_pipe_item_get(rcc))) { red_channel_client_send_item(rcc, pipe_item); } + if (red_channel_client_no_item_being_sent(rcc) && ring_is_empty(&rcc->pipe) + && rcc->stream->watch) { + rcc->channel->core->watch_update_mask(rcc->stream->watch, + SPICE_WATCH_EVENT_READ); + } rcc->during_send = FALSE; red_channel_client_unref(rcc); } @@ -1645,7 +1650,7 @@ void red_channel_pipe_item_init(RedChannel *channel, PipeItem *item, int type) item->type = type; } -static inline int validate_pipe_add(RedChannelClient *rcc, PipeItem *item) +static inline int prepare_pipe_add(RedChannelClient *rcc, PipeItem *item) { spice_assert(rcc && item); if (SPICE_UNLIKELY(!red_channel_client_is_connected(rcc))) { @@ -1653,16 +1658,21 @@ static inline int validate_pipe_add(RedChannelClient *rcc, PipeItem *item) red_channel_client_release_item(rcc, item, FALSE); return FALSE; } + if (ring_is_empty(&rcc->pipe) && rcc->stream->watch) { + rcc->channel->core->watch_update_mask(rcc->stream->watch, + SPICE_WATCH_EVENT_READ | + SPICE_WATCH_EVENT_WRITE); + } + rcc->pipe_size++; return TRUE; } void red_channel_client_pipe_add(RedChannelClient *rcc, PipeItem *item) { - if (!validate_pipe_add(rcc, item)) { + if (!prepare_pipe_add(rcc, item)) { return; } - rcc->pipe_size++; ring_add(&rcc->pipe, &item->link); } @@ -1676,10 +1686,9 @@ void red_channel_client_pipe_add_after(RedChannelClient *rcc, PipeItem *item, PipeItem *pos) { spice_assert(pos); - if (!validate_pipe_add(rcc, item)) { + if (!prepare_pipe_add(rcc, item)) { return; } - rcc->pipe_size++; ring_add_after(&item->link, &pos->link); } @@ -1692,19 +1701,17 @@ int red_channel_client_pipe_item_is_linked(RedChannelClient *rcc, void red_channel_client_pipe_add_tail_no_push(RedChannelClient *rcc, PipeItem *item) { - if (!validate_pipe_add(rcc, item)) { + if (!prepare_pipe_add(rcc, item)) { return; } - rcc->pipe_size++; ring_add_before(&item->link, &rcc->pipe); } void red_channel_client_pipe_add_tail(RedChannelClient *rcc, PipeItem *item) { - if (!validate_pipe_add(rcc, item)) { + if (!prepare_pipe_add(rcc, item)) { return; } - rcc->pipe_size++; ring_add_before(&item->link, &rcc->pipe); red_channel_client_push(rcc); } diff --git a/server/red-worker.c b/server/red-worker.c index 560d172..cf8e73d 100644 --- a/server/red-worker.c +++ b/server/red-worker.c @@ -321,16 +321,6 @@ static int red_process_display(RedWorker *worker, int *ring_is_empty) return n; } -static void red_push(RedWorker *worker) -{ - if (worker->cursor_channel) { - red_channel_push(RED_CHANNEL(worker->cursor_channel)); - } - if (worker->display_channel) { - red_channel_push(RED_CHANNEL(worker->display_channel)); - } -} - static void red_disconnect_display(RedWorker *worker) { spice_warning("update timeout"); @@ -1458,9 +1448,6 @@ static gboolean worker_source_dispatch(GSource *source, GSourceFunc callback, red_process_cursor(worker, &ring_is_empty); red_process_display(worker, &ring_is_empty); - /* TODO: remove me? that should be handled by watch out condition */ - red_push(worker); - return TRUE; } -- 2.4.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel