diff options
author | Hans de Goede <hdegoede@redhat.com> | 2011-08-18 07:29:15 -0700 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2011-08-24 14:10:36 +0200 |
commit | 09a3698650891ef51fffb3690e9cc97e5555d91f (patch) | |
tree | 2efcbc1c4329cf37ea266b465f95afbeddd2c9b7 /usbredirparser/usbredirparser.c | |
parent | 4fbe701ae6ae2ef5a08d75793f39e0e085bb74d4 (diff) |
libusbredir*: Add (limited) multi-threading support
Diffstat (limited to 'usbredirparser/usbredirparser.c')
-rw-r--r-- | usbredirparser/usbredirparser.c | 72 |
1 files changed, 60 insertions, 12 deletions
diff --git a/usbredirparser/usbredirparser.c b/usbredirparser/usbredirparser.c index 5a9ed56..6237b3b 100644 --- a/usbredirparser/usbredirparser.c +++ b/usbredirparser/usbredirparser.c @@ -24,6 +24,19 @@ #include <string.h> #include "usbredirparser.h" +/* Locking convenience macros */ +#define LOCK(parser) \ + do { \ + if ((parser)->lock) \ + (parser)->lock_func((parser)->lock); \ + } while (0) + +#define UNLOCK(parser) \ + do { \ + if ((parser)->lock) \ + (parser)->unlock_func((parser)->lock); \ + } while (0) + struct usbredirparser_buf { uint8_t *buf; int pos; @@ -39,6 +52,11 @@ struct usbredirparser_priv { uint32_t our_caps[USB_REDIR_CAPS_SIZE]; uint32_t peer_caps[USB_REDIR_CAPS_SIZE]; + usbredirparser_lock lock_func; + usbredirparser_unlock unlock_func; + usbredirparser_free_lock free_lock_func; + void *lock; + struct usb_redir_header header; uint8_t type_header[256]; int header_read; @@ -112,9 +130,33 @@ void usbredirparser_destroy(struct usbredirparser *parser_pub) wbuf = next_wbuf; } + if (parser->lock) + parser->free_lock_func(parser->lock); + free(parser); } +int usbredirparser_set_locking_funcs(struct usbredirparser *parser_pub, + usbredirparser_alloc_lock alloc_lock_func, + usbredirparser_lock lock_func, + usbredirparser_unlock unlock_func, + usbredirparser_free_lock free_lock_func) +{ + struct usbredirparser_priv *parser = + (struct usbredirparser_priv *)parser_pub; + + parser->lock_func = lock_func; + parser->unlock_func = unlock_func; + parser->free_lock_func = free_lock_func; + + parser->lock = alloc_lock_func(); + if (!parser->lock) { + ERROR("Out of memory allocating lock"); + return -1; + } + return 0; +} + int usbredirparser_peer_has_cap(struct usbredirparser *parser_pub, int cap) { struct usbredirparser_priv *parser = @@ -634,19 +676,22 @@ int usbredirparser_do_write(struct usbredirparser *parser_pub) { struct usbredirparser_priv *parser = (struct usbredirparser_priv *)parser_pub; - int w; struct usbredirparser_buf* wbuf; + int w, ret = 0; + LOCK(parser); for (;;) { wbuf = parser->write_buf; if (!wbuf) - return 0; + break; w = wbuf->len - wbuf->pos; w = parser->callb.write_func(parser->callb.priv, wbuf->buf + wbuf->pos, w); - if (w <= 0) - return w; + if (w <= 0) { + ret = -1; + break; + } /* See usbredirparser_write documentation */ if ((parser->flags & usbredirparser_fl_write_cb_owns_buffer) && @@ -661,6 +706,8 @@ int usbredirparser_do_write(struct usbredirparser *parser_pub) free(wbuf); } } + UNLOCK(parser); + return ret; } void usbredirparser_free_write_buffer(struct usbredirparser *parser, @@ -719,17 +766,18 @@ static void usbredirparser_queue(struct usbredirparser *parser_pub, memcpy(type_header_out, type_header_in, type_header_len); memcpy(data_out, data_in, data_len); + LOCK(parser); if (!parser->write_buf) { parser->write_buf = new_wbuf; - return; - } - - /* maybe we should limit the write_buf stack depth ? */ - wbuf = parser->write_buf; - while (wbuf->next) - wbuf = wbuf->next; + } else { + /* maybe we should limit the write_buf stack depth ? */ + wbuf = parser->write_buf; + while (wbuf->next) + wbuf = wbuf->next; - wbuf->next = new_wbuf; + wbuf->next = new_wbuf; + } + UNLOCK(parser); } void usbredirparser_send_device_connect(struct usbredirparser *parser, |