<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 24, 2014 at 8:06 PM, Jeremy White <span dir="ltr"><<a href="mailto:jwhite@codeweavers.com" target="_blank">jwhite@codeweavers.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">A MsgMainMultiMediaTime message on the main channel will be relayed<br>
through main_dispatcher so as to be fired in the context of the<br>
main (not worker) thread.<br>
<br>
In qemu, that thread happens to also be the thread that drives the<br>
audio channel, so it works.<br>
<br>
In XSpice, it is a different thread, which leads to unpleasant<br>
side effects. The predominant side effect I noticed was an infinite loop<br>
in snd_send_data.<br></blockquote><div><br></div><div>Is this difficult to solve? It seems the thread is reading from a fd and pushing to spice server. Couldn't this be done from X main loop?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
This patch uses a mutex to prevent such collisions.<br></blockquote><div><br></div><div>Is the mutex supposed to protect the whole SndChannel struct?It seems there are various code path that could be called with or without the lock held (snd_playback_send callback, for example). I would rather move the protected bits into a substructure, and make sure only access is made with the lock. <br><br></div><div>But I think we are going in a dangerous place if we start making spice server MT-safe api<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Signed-off-by: Jeremy White <<a href="mailto:jwhite@codeweavers.com">jwhite@codeweavers.com</a>><br>
---<br>
server/snd_worker.c | 30 ++++++++++++++++++++++++++++--<br>
1 file changed, 28 insertions(+), 2 deletions(-)<br>
<br>
diff --git a/server/snd_worker.c b/server/snd_worker.c<br>
index 70148b7..b977bed 100644<br>
--- a/server/snd_worker.c<br>
+++ b/server/snd_worker.c<br>
@@ -115,6 +115,8 @@ struct SndChannel {<br>
snd_channel_handle_message_proc handle_message;<br>
snd_channel_on_message_done_proc on_message_done;<br>
snd_channel_cleanup_channel_proc cleanup;<br>
+<br>
+ pthread_mutex_t lock;<br>
};<br>
<br>
typedef struct PlaybackChannel PlaybackChannel;<br>
@@ -220,8 +222,21 @@ static void snd_disconnect_channel(SndChannel *channel)<br>
spice_marshaller_destroy(channel->send_data.marshaller);<br>
snd_channel_put(channel);<br>
worker->connection = NULL;<br>
+<br>
+ pthread_mutex_destroy(&channel->lock);<br>
+}<br>
+<br>
+static int snd_lock(SndChannel *channel)<br>
+{<br>
+ return pthread_mutex_lock(&channel->lock);<br>
+}<br>
+<br>
+static void snd_unlock(SndChannel *channel)<br>
+{<br>
+ pthread_mutex_unlock(&channel->lock);<br>
}<br>
<br>
+<br>
static void snd_playback_free_frame(PlaybackChannel *playback_channel, AudioFrame *frame)<br>
{<br>
frame->channel = playback_channel;<br>
@@ -967,6 +982,8 @@ static SndChannel *__new_channel(SndWorker *worker, int size, uint32_t channel_i<br>
if (!channel->channel_client) {<br>
goto error2;<br>
}<br>
+<br>
+ pthread_mutex_init(&channel->lock, NULL);<br>
return channel;<br>
<br>
error2:<br>
@@ -1105,10 +1122,15 @@ SPICE_GNUC_VISIBLE void spice_server_playback_put_samples(SpicePlaybackInstance<br>
frame = SPICE_CONTAINEROF(samples, AudioFrame, samples);<br>
playback_channel = frame->channel;<br>
spice_assert(playback_channel);<br>
+<br>
+ if (snd_lock(&playback_channel->base) != 0)<br>
+ return;<br>
+<br>
if (!snd_channel_put(&playback_channel->base) ||<br>
sin->st->worker.connection != &playback_channel->base) {<br>
/* lost last reference, channel has been destroyed previously */<br>
spice_info("audio samples belong to a disconnected channel");<br>
+ snd_unlock(&playback_channel->base);<br>
return;<br>
}<br>
spice_assert(playback_channel->base.active);<br>
@@ -1121,6 +1143,7 @@ SPICE_GNUC_VISIBLE void spice_server_playback_put_samples(SpicePlaybackInstance<br>
playback_channel->pending_frame = frame;<br>
snd_set_command(&playback_channel->base, SND_PLAYBACK_PCM_MASK);<br>
snd_playback_send(&playback_channel->base);<br>
+ snd_unlock(&playback_channel->base);<br>
}<br>
<br>
void snd_set_playback_latency(RedClient *client, uint32_t latency)<br>
@@ -1136,8 +1159,11 @@ void snd_set_playback_latency(RedClient *client, uint32_t latency)<br>
PlaybackChannel* playback = (PlaybackChannel*)now->connection;<br>
<br>
playback->latency = latency;<br>
- snd_set_command(now->connection, SND_PLAYBACK_LATENCY_MASK);<br>
- snd_playback_send(now->connection);<br>
+ if (snd_lock(now->connection) == 0) {<br>
+ snd_set_command(now->connection, SND_PLAYBACK_LATENCY_MASK);<br>
+ snd_playback_send(now->connection);<br>
+ snd_unlock(now->connection);<br>
+ }<br>
} else {<br>
spice_debug("client doesn't not support SPICE_PLAYBACK_CAP_LATENCY");<br>
}<br>
<span class=""><font color="#888888">--<br>
1.7.10.4<br>
<br>
_______________________________________________<br>
Spice-devel mailing list<br>
<a href="mailto:Spice-devel@lists.freedesktop.org">Spice-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/spice-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/spice-devel</a><br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>Marc-André Lureau
</div></div>