Blame SOURCES/0011-server-move-three-functions-to-red_channel.patch

e2c81d
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
20333d
From: Alon Levy <alevy@redhat.com>
20333d
Date: Mon, 12 Aug 2013 15:01:42 +0300
20333d
Subject: [PATCH] server: move three functions to red_channel
20333d
20333d
Three blocking functions, one was split to leave the display channel
20333d
specific referencing of the DrawablePipeItem being sent inside
20333d
red_worker, but the rest (most) of the timeout logic was moved to
20333d
red_channel, including the associated constants.
20333d
20333d
Moved functions:
20333d
red_channel_client_wait_pipe_item_sent
20333d
red_wait_outgoing_item
20333d
red_wait_all_sent
20333d
20333d
Introduces red_time.h & red_time.c for a small helper function dealing
20333d
with time.h
20333d
20333d
https://bugzilla.redhat.com/show_bug.cgi?id=1016795
20333d
Conflicts:
20333d
	server/red_worker.c
20333d
---
20333d
 server/red_channel.c | 106 ++++++++++++++++++++++++++++++++++++++++++++
20333d
 server/red_channel.h |  10 +++++
20333d
 server/red_time.c    |   1 +
20333d
 server/red_time.h    |  15 +++++++
20333d
 server/red_worker.c  | 121 +--------------------------------------------------
20333d
 5 files changed, 134 insertions(+), 119 deletions(-)
20333d
 create mode 100644 server/red_time.c
20333d
 create mode 100644 server/red_time.h
20333d
20333d
diff --git a/server/red_channel.c b/server/red_channel.c
20333d
index 1a57db5..555d376 100644
20333d
--- a/server/red_channel.c
20333d
+++ b/server/red_channel.c
20333d
@@ -38,6 +38,7 @@
20333d
 #include "red_channel.h"
20333d
 #include "reds.h"
20333d
 #include "main_dispatcher.h"
20333d
+#include "red_time.h"
20333d
 
20333d
 typedef struct EmptyMsgPipeItem {
20333d
     PipeItem base;
20333d
@@ -47,6 +48,12 @@ typedef struct EmptyMsgPipeItem {
20333d
 #define PING_TEST_TIMEOUT_MS 15000
20333d
 #define PING_TEST_IDLE_NET_TIMEOUT_MS 100
20333d
 
20333d
+#define DETACH_TIMEOUT 15000000000ULL //nano
20333d
+#define DETACH_SLEEP_DURATION 10000 //micro
20333d
+
20333d
+#define CHANNEL_PUSH_TIMEOUT 30000000000ULL //nano
20333d
+#define CHANNEL_PUSH_SLEEP_DURATION 10000 //micro
20333d
+
20333d
 enum QosPingState {
20333d
     PING_STATE_NONE,
20333d
     PING_STATE_TIMER,
20333d
@@ -2183,3 +2190,102 @@ uint32_t red_channel_sum_pipes_size(RedChannel *channel)
20333d
     }
20333d
     return sum;
20333d
 }
20333d
+
20333d
+void red_wait_outgoing_item(RedChannelClient *rcc)
20333d
+{
20333d
+    uint64_t end_time;
20333d
+    int blocked;
20333d
+
20333d
+    if (!red_channel_client_blocked(rcc)) {
20333d
+        return;
20333d
+    }
20333d
+    end_time = red_now() + DETACH_TIMEOUT;
20333d
+    spice_info("blocked");
20333d
+
20333d
+    do {
20333d
+        usleep(DETACH_SLEEP_DURATION);
20333d
+        red_channel_client_receive(rcc);
20333d
+        red_channel_client_send(rcc);
20333d
+    } while ((blocked = red_channel_client_blocked(rcc)) && red_now() < end_time);
20333d
+
20333d
+    if (blocked) {
20333d
+        spice_warning("timeout");
20333d
+        // TODO - shutting down the socket but we still need to trigger
20333d
+        // disconnection. Right now we wait for main channel to error for that.
20333d
+        red_channel_client_shutdown(rcc);
20333d
+    } else {
20333d
+        spice_assert(red_channel_client_no_item_being_sent(rcc));
20333d
+    }
20333d
+}
20333d
+
20333d
+/* TODO: more evil sync stuff. anything with the word wait in it's name. */
20333d
+void red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
20333d
+                                            PipeItem *item)
20333d
+{
20333d
+    uint64_t end_time;
20333d
+    int item_in_pipe;
20333d
+
20333d
+    spice_info(NULL);
20333d
+
20333d
+    end_time = red_now() + CHANNEL_PUSH_TIMEOUT;
20333d
+
20333d
+    rcc->channel->channel_cbs.hold_item(rcc, item);
20333d
+
20333d
+    if (red_channel_client_blocked(rcc)) {
20333d
+        red_channel_client_receive(rcc);
20333d
+        red_channel_client_send(rcc);
20333d
+    }
20333d
+    red_channel_client_push(rcc);
20333d
+
20333d
+    while((item_in_pipe = ring_item_is_linked(&item->link)) && (red_now() < end_time)) {
20333d
+        usleep(CHANNEL_PUSH_SLEEP_DURATION);
20333d
+        red_channel_client_receive(rcc);
20333d
+        red_channel_client_send(rcc);
20333d
+        red_channel_client_push(rcc);
20333d
+    }
20333d
+
20333d
+    if (item_in_pipe) {
20333d
+        spice_warning("timeout");
20333d
+        red_channel_client_disconnect(rcc);
20333d
+    } else {
20333d
+        red_wait_outgoing_item(rcc);
20333d
+    }
20333d
+    red_channel_client_release_item(rcc, item, TRUE);
20333d
+}
20333d
+
20333d
+static void rcc_shutdown_if_pending_send(RedChannelClient *rcc)
20333d
+{
20333d
+    if (red_channel_client_blocked(rcc) || rcc->pipe_size > 0) {
20333d
+        red_channel_client_shutdown(rcc);
20333d
+    } else {
20333d
+        spice_assert(red_channel_client_no_item_being_sent(rcc));
20333d
+    }
20333d
+}
20333d
+
20333d
+void red_wait_all_sent(RedChannel *channel)
20333d
+{
20333d
+    uint64_t end_time;
20333d
+    uint32_t max_pipe_size;
20333d
+    int blocked = FALSE;
20333d
+
20333d
+    end_time = red_now() + DETACH_TIMEOUT;
20333d
+
20333d
+    red_channel_push(channel);
20333d
+    while (((max_pipe_size = red_channel_max_pipe_size(channel)) ||
20333d
+           (blocked = red_channel_any_blocked(channel))) &&
20333d
+           red_now() < end_time) {
20333d
+        spice_debug("pipe-size %u blocked %d", max_pipe_size, blocked);
20333d
+        usleep(DETACH_SLEEP_DURATION);
20333d
+        red_channel_receive(channel);
20333d
+        red_channel_send(channel);
20333d
+        red_channel_push(channel);
20333d
+    }
20333d
+
20333d
+    if (max_pipe_size || blocked) {
20333d
+        spice_printerr("timeout: pending out messages exist (pipe-size %u, blocked %d)",
20333d
+                       max_pipe_size, blocked);
20333d
+        red_channel_apply_clients(channel, rcc_shutdown_if_pending_send);
20333d
+    } else {
20333d
+        spice_assert(red_channel_no_item_being_sent(channel));
20333d
+    }
20333d
+}
20333d
diff --git a/server/red_channel.h b/server/red_channel.h
20333d
index 0dd73ea..b2a3a6a 100644
20333d
--- a/server/red_channel.h
20333d
+++ b/server/red_channel.h
20333d
@@ -596,4 +596,14 @@ int red_client_during_migrate_at_target(RedClient *client);
20333d
 
20333d
 void red_client_migrate(RedClient *client);
20333d
 
20333d
+/* blocking function */
20333d
+void red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
20333d
+                                            PipeItem *item);
20333d
+
20333d
+/* blocking function */
20333d
+void red_wait_outgoing_item(RedChannelClient *rcc);
20333d
+
20333d
+/* blocking function */
20333d
+void red_wait_all_sent(RedChannel *channel);
20333d
+
20333d
 #endif
20333d
diff --git a/server/red_time.c b/server/red_time.c
20333d
new file mode 100644
20333d
index 0000000..8b13789
20333d
--- /dev/null
20333d
+++ b/server/red_time.c
20333d
@@ -0,0 +1 @@
20333d
+
20333d
diff --git a/server/red_time.h b/server/red_time.h
20333d
new file mode 100644
20333d
index 0000000..ffa97f2
20333d
--- /dev/null
20333d
+++ b/server/red_time.h
20333d
@@ -0,0 +1,15 @@
20333d
+#ifndef H_RED_TIME
20333d
+#define H_RED_TIME
20333d
+
20333d
+#include <time.h>
20333d
+
20333d
+static inline uint64_t red_now(void)
20333d
+{
20333d
+    struct timespec time;
20333d
+
20333d
+    clock_gettime(CLOCK_MONOTONIC, &time);
20333d
+
20333d
+    return ((uint64_t) time.tv_sec) * 1000000000 + time.tv_nsec;
20333d
+}
20333d
+
20333d
+#endif
20333d
diff --git a/server/red_worker.c b/server/red_worker.c
20333d
index a4f0663..b3a957e 100644
20333d
--- a/server/red_worker.c
20333d
+++ b/server/red_worker.c
20333d
@@ -82,6 +82,7 @@
20333d
 #include "migration_protocol.h"
20333d
 #include "spice_timer_queue.h"
20333d
 #include "main_dispatcher.h"
20333d
+#include "red_time.h"
20333d
 
20333d
 //#define COMPRESS_STAT
20333d
 //#define DUMP_BITMAP
20333d
@@ -97,12 +98,6 @@
20333d
 #define CMD_RING_POLL_TIMEOUT 10 //milli
20333d
 #define CMD_RING_POLL_RETRIES 200
20333d
 
20333d
-#define DETACH_TIMEOUT 15000000000ULL //nano
20333d
-#define DETACH_SLEEP_DURATION 10000 //micro
20333d
-
20333d
-#define CHANNEL_PUSH_TIMEOUT 30000000000ULL //nano
20333d
-#define CHANNEL_PUSH_SLEEP_DURATION 10000 //micro
20333d
-
20333d
 #define DISPLAY_CLIENT_TIMEOUT 30000000000ULL //nano
20333d
 #define DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT 10000000000ULL //nano, 10 sec
20333d
 #define DISPLAY_CLIENT_RETRY_INTERVAL 10000 //micro
20333d
@@ -1098,14 +1093,12 @@ static void cursor_channel_client_release_item_before_push(CursorChannelClient *
20333d
                                                            PipeItem *item);
20333d
 static void cursor_channel_client_release_item_after_push(CursorChannelClient *ccc,
20333d
                                                           PipeItem *item);
20333d
-static void red_wait_pipe_item_sent(RedChannelClient *rcc, PipeItem *item);
20333d
 
20333d
 #ifdef DUMP_BITMAP
20333d
 static void dump_bitmap(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_id);
20333d
 #endif
20333d
 
20333d
 static void red_push_monitors_config(DisplayChannelClient *dcc);
20333d
-static inline uint64_t red_now(void);
20333d
 
20333d
 /*
20333d
  * Macros to make iterating over stuff easier
20333d
@@ -2098,12 +2091,10 @@ static void red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int
20333d
     }
20333d
 
20333d
     if (item) {
20333d
-        red_wait_pipe_item_sent(&dcc->common.base, item);
20333d
+        red_channel_client_wait_pipe_item_sent(&dcc->common.base, item);
20333d
     }
20333d
 }
20333d
 
20333d
-static void red_wait_outgoing_item(RedChannelClient *rcc);
20333d
-
20333d
 static void red_clear_surface_drawables_from_pipes(RedWorker *worker, int surface_id,
20333d
     int force, int wait_for_outgoing_item)
20333d
 {
20333d
@@ -5088,15 +5079,6 @@ static void qxl_process_cursor(RedWorker *worker, RedCursorCmd *cursor_cmd, uint
20333d
     red_release_cursor(worker, cursor_item);
20333d
 }
20333d
 
20333d
-static inline uint64_t red_now(void)
20333d
-{
20333d
-    struct timespec time;
20333d
-
20333d
-    clock_gettime(CLOCK_MONOTONIC, &time);
20333d
-
20333d
-    return ((uint64_t) time.tv_sec) * 1000000000 + time.tv_nsec;
20333d
-}
20333d
-
20333d
 static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int *ring_is_empty)
20333d
 {
20333d
     QXLCommandExt ext_cmd;
20333d
@@ -10988,105 +10970,6 @@ typedef struct __attribute__ ((__packed__)) CursorData {
20333d
     SpiceCursor _cursor;
20333d
 } CursorData;
20333d
 
20333d
-static void red_wait_outgoing_item(RedChannelClient *rcc)
20333d
-{
20333d
-    uint64_t end_time;
20333d
-    int blocked;
20333d
-
20333d
-    if (!red_channel_client_blocked(rcc)) {
20333d
-        return;
20333d
-    }
20333d
-    end_time = red_now() + DETACH_TIMEOUT;
20333d
-    spice_info("blocked");
20333d
-
20333d
-    do {
20333d
-        usleep(DETACH_SLEEP_DURATION);
20333d
-        red_channel_client_receive(rcc);
20333d
-        red_channel_client_send(rcc);
20333d
-    } while ((blocked = red_channel_client_blocked(rcc)) && red_now() < end_time);
20333d
-
20333d
-    if (blocked) {
20333d
-        spice_warning("timeout");
20333d
-        // TODO - shutting down the socket but we still need to trigger
20333d
-        // disconnection. Right now we wait for main channel to error for that.
20333d
-        red_channel_client_shutdown(rcc);
20333d
-    } else {
20333d
-        spice_assert(red_channel_client_no_item_being_sent(rcc));
20333d
-    }
20333d
-}
20333d
-
20333d
-static void rcc_shutdown_if_pending_send(RedChannelClient *rcc)
20333d
-{
20333d
-    if (red_channel_client_blocked(rcc) || rcc->pipe_size > 0) {
20333d
-        red_channel_client_shutdown(rcc);
20333d
-    } else {
20333d
-        spice_assert(red_channel_client_no_item_being_sent(rcc));
20333d
-    }
20333d
-}
20333d
-
20333d
-static void red_wait_all_sent(RedChannel *channel)
20333d
-{
20333d
-    uint64_t end_time;
20333d
-    uint32_t max_pipe_size;
20333d
-    int blocked = FALSE;
20333d
-
20333d
-    end_time = red_now() + DETACH_TIMEOUT;
20333d
-
20333d
-    red_channel_push(channel);
20333d
-    while (((max_pipe_size = red_channel_max_pipe_size(channel)) ||
20333d
-           (blocked = red_channel_any_blocked(channel))) &&
20333d
-           red_now() < end_time) {
20333d
-        spice_debug("pipe-size %u blocked %d", max_pipe_size, blocked);
20333d
-        usleep(DETACH_SLEEP_DURATION);
20333d
-        red_channel_receive(channel);
20333d
-        red_channel_send(channel);
20333d
-        red_channel_push(channel);
20333d
-    }
20333d
-
20333d
-    if (max_pipe_size || blocked) {
20333d
-        spice_printerr("timeout: pending out messages exist (pipe-size %u, blocked %d)",
20333d
-                       max_pipe_size, blocked);
20333d
-        red_channel_apply_clients(channel, rcc_shutdown_if_pending_send);
20333d
-    } else {
20333d
-        spice_assert(red_channel_no_item_being_sent(channel));
20333d
-    }
20333d
-}
20333d
-
20333d
-/* TODO: more evil sync stuff. anything with the word wait in it's name. */
20333d
-static void red_wait_pipe_item_sent(RedChannelClient *rcc, PipeItem *item)
20333d
-{
20333d
-    DrawablePipeItem *dpi;
20333d
-    uint64_t end_time;
20333d
-    int item_in_pipe;
20333d
-
20333d
-    spice_info(NULL);
20333d
-    dpi = SPICE_CONTAINEROF(item, DrawablePipeItem, dpi_pipe_item);
20333d
-    ref_drawable_pipe_item(dpi);
20333d
-
20333d
-    end_time = red_now() + CHANNEL_PUSH_TIMEOUT;
20333d
-
20333d
-    if (red_channel_client_blocked(rcc)) {
20333d
-        red_channel_client_receive(rcc);
20333d
-        red_channel_client_send(rcc);
20333d
-    }
20333d
-    red_channel_client_push(rcc);
20333d
-
20333d
-    while((item_in_pipe = ring_item_is_linked(&item->link)) && (red_now() < end_time)) {
20333d
-        usleep(CHANNEL_PUSH_SLEEP_DURATION);
20333d
-        red_channel_client_receive(rcc);
20333d
-        red_channel_client_send(rcc);
20333d
-        red_channel_client_push(rcc);
20333d
-    }
20333d
-
20333d
-    if (item_in_pipe) {
20333d
-        spice_warning("timeout");
20333d
-        red_channel_client_disconnect(rcc);
20333d
-    } else {
20333d
-        red_wait_outgoing_item(rcc);
20333d
-    }
20333d
-    put_drawable_pipe_item(dpi);
20333d
-}
20333d
-
20333d
 static void surface_dirty_region_to_rects(RedSurface *surface,
20333d
                                           QXLRect *qxl_dirty_rects,
20333d
                                           uint32_t num_dirty_rects,