[Spice-devel] [PATCH spice-gtk 07/10] usbredir: Handle usb events from a thread
Christophe Fergeau
cfergeau at redhat.com
Mon Jan 2 05:23:13 PST 2012
On Mon, Dec 19, 2011 at 12:24:40PM +0100, Hans de Goede wrote:
> This solves various latency issues with USB handling.
>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> ---
> gtk/channel-usbredir.c | 5 +++++
> gtk/usb-device-manager.c | 45 ++++++++++++++++++++++++++++++++-------------
> 2 files changed, 37 insertions(+), 13 deletions(-)
>
> diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c
> index dfd1655..e14088a 100644
> --- a/gtk/channel-usbredir.c
> +++ b/gtk/channel-usbredir.c
> @@ -352,6 +352,11 @@ void spice_usbredir_channel_disconnect(SpiceUsbredirChannel *channel)
> case STATE_CONNECTING:
> case STATE_CONNECTED:
> spice_channel_disconnect(SPICE_CHANNEL(channel), SPICE_CHANNEL_NONE);
> + /*
> + * This sets the usb event thread run condition to FALSE, therefor
> + * it must be done before usbredirhost_close, as usbredirhost_close
> + * will interrupt the libusb_handle_events call in the thread.
> + */
> spice_usb_device_manager_stop_event_listening(
> spice_usb_device_manager_get(
> spice_channel_get_session(SPICE_CHANNEL(channel)),
> diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
> index 6fba6f6..44ed84d 100644
> --- a/gtk/usb-device-manager.c
> +++ b/gtk/usb-device-manager.c
> @@ -26,8 +26,8 @@
> #include "glib-compat.h"
>
> #ifdef USE_USBREDIR
> -#include <gusb/gusb-source.h>
> #include <gusb/gusb-device-list.h>
> +#include <gusb/gusb-context-private.h>
> #include "channel-usbredir-priv.h"
> #endif
>
> @@ -91,8 +91,9 @@ struct _SpiceUsbDeviceManagerPrivate {
> #ifdef USE_USBREDIR
> GUsbContext *context;
> GUsbDeviceList *devlist;
> - GUsbSource *source;
> int event_listeners;
> + GThread *event_thread;
> + gboolean event_thread_run;
> #endif
> GPtrArray *devices;
> GPtrArray *channels;
> @@ -204,6 +205,9 @@ static void spice_usb_device_manager_finalize(GObject *gobject)
> SpiceUsbDeviceManagerPrivate *priv = self->priv;
>
> #ifdef USE_USBREDIR
> + if (priv->event_thread)
> + g_thread_join(priv->event_thread);
> +
> if (priv->devlist) {
> g_object_unref(priv->devlist);
> g_object_unref(priv->context);
> @@ -480,6 +484,18 @@ static void spice_usb_device_manager_channel_connect_cb(
> /* ------------------------------------------------------------------ */
> /* private api */
>
> +static gpointer spice_usb_device_magager_usb_ev_thread(gpointer user_data)
s/magager/manager
> +{
> + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(user_data);
> + SpiceUsbDeviceManagerPrivate *priv = self->priv;
> +
> + while (priv->event_thread_run) {
> + libusb_handle_events(_g_usb_context_get_context(priv->context));
> + }
Maybe we should log something when libusb_handle_events returns
LIBUSB_ERROR_* ?
> +
> + return NULL;
> +}
> +
> gboolean spice_usb_device_manager_start_event_listening(
> SpiceUsbDeviceManager *self, GError **err)
> {
> @@ -491,10 +507,18 @@ gboolean spice_usb_device_manager_start_event_listening(
> if (priv->event_listeners > 1)
> return TRUE;
>
> - g_return_val_if_fail(priv->source == NULL, FALSE);
> -
> - priv->source = g_usb_source_new(priv->main_context, priv->context, err);
> - return priv->source != NULL;
> + /* We don't join the thread when we stop event listening, as the
> + libusb_handle_events call in the thread won't exit until the
> + libusb_close call for the device is made from usbredirhost_close. */
> + if (priv->event_thread) {
> + g_thread_join(priv->event_thread);
> + priv->event_thread = NULL;
> + }
> + priv->event_thread_run = TRUE;
> + priv->event_thread = g_thread_create(
> + spice_usb_device_magager_usb_ev_thread,
> + self, TRUE, err);
Do we need to join threads at all? Not needing to call g_thread_join would
make the code simpler. Ie the 3rd arg could be FALSE here.
Christophe
> + return priv->event_thread != NULL;
> }
>
> void spice_usb_device_manager_stop_event_listening(
> @@ -505,13 +529,8 @@ void spice_usb_device_manager_stop_event_listening(
> g_return_if_fail(priv->event_listeners > 0);
>
> priv->event_listeners--;
> - if (priv->event_listeners != 0)
> - return;
> -
> - g_return_if_fail(priv->source != NULL);
> -
> - g_usb_source_destroy(priv->source);
> - priv->source = NULL;
> + if (priv->event_listeners == 0)
> + priv->event_thread_run = FALSE;
> }
> #endif
>
> --
> 1.7.7.4
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20120102/1d0a506a/attachment.pgp>
More information about the Spice-devel
mailing list