Re: Usb redirection

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,



On 12/27/2012 07:23 AM, Jackson wrote:
OK! in my situation, my webcam can redirect to VM, then, I open amcap and check
the code. I find that there are two ways running into the same for loop, and I'm
not sure it is normal or not?

first route
the client receive message through usbredir channel, then
1. usbredir_handle_msg
2. usbredirparser_do_read
3. case usb_redir_stop_interrupt_receiving:
    parser->callb.stop_interrupt_receiving_func(...)
4. usbredirhost_stop_interrupt_receiving
5. usbredir_write_flush_callback
6. usbredirparser_do_write
7. in loop, for(;;){}

second route
another thread run while loop
    rc = libusb_handle_events(priv->context);
1. spice_usb_device_manager_usb_ev_thread
2. libusb_handle_events
3. libusb_handle_events_timeout_completed
4. handle_events
5. windows_handle_events
6. windows_handle_callback
    case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
        windows_transfer_callback(itransfer, io_result, io_size);
7. windows_transfer_callback
8. usbi_handle_transfer_completion
9. usbredirhost_interrupt_packet_complete
10. usbredir_write_flush_callback
11. usbredirparser_do_write
12. in loop, for(;;){}

Yes this is normal, note that both threads can *not* enter the
loop at the same time, as usbredirparser_do_write starts like this:

int usbredirparser_do_write(struct usbredirparser *parser_pub)
{
    struct usbredirparser_priv *parser =
        (struct usbredirparser_priv *)parser_pub;
    struct usbredirparser_buf* wbuf;
    int w, ret = 0;

    LOCK(parser);
    for (;;) {

Notice the LOCK call there, now that may be a nop when the user
of usbredirparser does not use any locks, but spice-gtk
does use the locks, it creates the parser through usbredirhost
with locking functions, from spice-gtk/gtk/gtk/channel-usbredir.c

void spice_usbredir_channel_set_context(SpiceUsbredirChannel *channel,
                                        libusb_context       *context)
{
    SpiceUsbredirChannelPrivate *priv = channel->priv;

    g_return_if_fail(priv->host == NULL);

    priv->context = context;
    priv->host = usbredirhost_open_full(
                                   context, NULL,
                                   usbredir_log,
                                   usbredir_read_callback,
                                   usbredir_write_callback,
                                   usbredir_write_flush_callback,
                                   usbredir_alloc_lock,
                                   usbredir_lock_lock,
                                   usbredir_unlock_lock,
                                   usbredir_free_lock,
                                   channel, PACKAGE_STRING,
                                   spice_util_get_debug() ? usbredirparser_debu
                                   usbredirhost_fl_write_cb_owns_buffer);

Note how it specifies lock alloc, lock, unlock and free functions,
so usbredirhost / usbredirparser will use locking and only one
thread can be running in the for loop at a time (and once the second
thread loop runs it will exit immediately since the flush is already
done).

Regards,

Hans
_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]