Re: [linux-audio-dev] discussion about development overlap

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] discussion about development overlap
From: Paul Barton-Davis (pbd_AT_Op.Net)
Date: Thu Sep 28 2000 - 17:48:08 EEST


>> ardour's audio thread doesn't block for anything except page faults
>> and the audio device. page faults will not happen either away if
>> mlockall() is called. there are no mutexes and no system calls in the
>> audio thread once it starts running its main loop.
>
>sounds good !
>just for completeness, one more question:
>(no time to read your code for now :-( )
>
>How do you manage audio<-->GUI and audio<-->diskthread
>communicaion ?

the audio thread's only communication with the disk thread is to wake
it up using pthread_cond_signal() (though it might already be
running). everything else is done with suitably atomic operations. the
index of the buffer that next needs flushing to disk is only ever
adjusted by the disk thread; the index of the buffer currently being
read from/written to in the audio thread is only ever adjusted by that
thread. we assume that read access to the variable by the "opposing"
thread is atomic, though i should probably enforce this with atomic_t.
in the terms you may be used to thinking in, i have a lock-free
ringbuffer containing pointers to data buffers, and the audio thread
and disk thread are cycling round the ringbuffer to get the locations
of the buffers they should be operating with. its not implemented
in this way, but the effect is more or less identical.

there is almost no GUI communication with the audio thread. as you
guessed, the main communication is for transport state change
requests.

first, you need to know that a Tape object is derived from an
AudioThing (think of it like a plugin) and a Transport. transport
state changes are sent to a Transport object; the audio thread
interacts with an AudioThing.

transport state change requests are queued by the GUI in a lock-free
FIFO owned by a Transport object. when the audio thread runs its
current "AudioThing", the Tape (derived, remember?) checks the queue
of state change requests before it does anything else. if it needs to
do something with the transport state, it invariably creates a new
thread to take care of it. it does this because this will inevitably
involve some disk i/o, meaning that we can't do it in the context of
the process() call; before it starts that thread, it marks it own
state as "changing". while this state condition is still set,
subsequent "process()" invocations by the audiothread cause the object
behaves as if the transport mechanism were not moving (i.e. silence).

  (note: in theory, this means that the audio thread might block
         while the new thread is created. however, thread creation
         is so damn fast and so deterministic that this is
         not an issue. if it were forking, the story might be
         different.)

the only other example of GUI->audio thread communication is to load
or unload an AudioThing, which is also done using a lock-free
FIFO. the audio thread checks for requests there just after it wakes
from poll(2), and if necessary, it changes its notion of its current
audiothing before calling process() (if appropriate).

>For the transfer of samples between disk thread and audio thread,
>you probably use shared mem with some sort of lock-free structure,
                  
                  ^^^^^^^^^^^
                  
well, yes, its all threads, so its all shared memory by default.

there are a couple of conditions that cause ardour to miss samples,
but these are all kernel related, and nothing (as far as i can tell)
to do with my code.

hope this helps.

--p


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Thu Sep 28 2000 - 19:27:41 EEST