[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [fluid-dev] Thread safety
Re: [fluid-dev] Thread safety
Wed, 20 May 2009 14:09:11 -0400
Internet Messaging Program (IMP) H3 (4.1.6)
Quoting David Henningsson <address@hidden>:
The proposed change is that incoming events will be pushed into the
sequencer queue by the midi thread, then popped and processed by the
audio thread. (The call stack for the audio thread would be:
fluid_synth_one_block -> fluid_sample_timer_process ->
fluid_sequencer_process -> fluid_seq_fluidsynth_callback ->
fluid_synth_noteon and friends)
However, if you say that Swami expects fluid_synth_t to be somewhat
thread-safe (just had a five-minute look a qsynth and at first glance it
seems to expect the same), perhaps it would be bad to enforce the
single-threaded synth at this point. Besides, I like the current idea of
starving the MIDI threads preferred to underrunning the audio in a
heavy-load situation. And that would break.
Yeah, I'm tending to think that trying to serialize everything into
one thread, could be a bad idea. Especially if we want to try to
provide multi-CPU voice processing support in the future. Your
initial analysis has got me excited though on this subject and I would
like to put some time into this too.
I think it would help to identify the areas where mutual exclusion
needs to occur, between the synthesis thread and MIDI event thread(s).
Just some initial thoughts, from memory (haven't actually reviewed the
code at this point):
- fluid_synth_t parameters (reverb/chorus/etc)
- Voice pool activate/deactivate of a voice and voice acquisition
- Voice parameter changes
A lot of FluidSynth assumes that integers can be atomically assigned
to. I think this assumption does not hold true on multi-CPU systems,
which could lead to unexpected behavior. Identifying groups of
parameters which are dependent on each other is also needed.
I wonder what the effect would be of using mutexes. In real life, how
bad would the lock contention be and would it lead to audio underruns?
Identifying the areas where mutexes are needed would help with this.
So the thread synchronization is limited to the sequencer. Here's the
suggested rules for using the sequencer in a thread-safe way:
- Only one thread at a time can call fluid_sequencer_process. This would
normally be the audio thread, via the sample timer callback.
- Any thread can call fluid_sequencer_send_at. The shortcut from
fluid_sequencer_send_at to fluid_sequencer_send_now is removed. This is
a subtle change of behavior but it is more consistent with the
documentation (i e "MAKES A COPY").
- fluid_sequencer_get_tick can be called from any thread (and should be
implemented with glib atomic integers).
- fluid_sequencer_send_now and fluid_sequencer_process are the only
public API calls that can result in midi events being sent. Midi events
are sent before the call returns and in the context of the calling
- Don't mess around with registering clients, or anything else, while
another thread makes a call to the sequencer.
A question would be whether this means we should leave up to the
libfluidsynth user to insert a sequencer in the midi processing chain,
or if we should create it automatically behind the scenes somehow (and
if so, what component should create it?). What do you think?
I don't think I fully understand this last bit. I guess all events
would go through the sequencer? If that were the case, I could see how
the fluid_synth_t would create it. Maybe even the fluid_synth_noteon
and friends could go through this?
Right. But if we were to go that way, perhaps we need all calls to go
through the sequencer, not only the ones that translate directly to a
midi event. Which probably means additional work.
My patch - in its current state - does not touch the synth. It changes
the sequencer according to the text above, and fluidsynth.c manually
inserts a sequencer between the midi router and the synth. So
libfluidsynth applications such as Swami and qsynth will neither suffer
or gain from this patch, unless they do the same.
What do you say if we leave it at that for the moment, I commit the
patch and we can all test it to see if we find any difference in latency
or stability when we use fluidsynth from the command line?
And at a later point in time we could review the synth threading a bit
more deep, to see if we can improve the situation (with regards to
segfaults, parallellization, stalls etc)?
Lets hold off on the patch for the moment. I want to have a look over
the lot myself to get a better idea of how we might proceed.