[alsa-devel] problems writing pcm driver

Trent Piepho xyzzy at speakeasy.org
Wed Aug 22 11:54:28 CEST 2007

On Wed, 22 Aug 2007, Takashi Iwai wrote:
> > On Tue, 21 Aug 2007, Takashi Iwai wrote:
> > > At Mon, 20 Aug 2007 13:47:48 -0700 (PDT),
> > > Trent Piepho wrote:
> > > > Atomicity:
> > > > trigger, pointer, and ack are atomic with respect to themselves.  e.g., two
> > > > copies of the trigger callback can't be running at the same time.  That much
> > > > is clear.  But are they atomic with respect to each other?  Can the trigger
> > > > callback run at the same time as the pointer callback?  How about the atomic
> > > > callbacks with respect to the non-atomic ones?  Can trigger run at the same
> > > > time as prepare?
> > >
> > > No, these callbacks are exclusive.  In principle, they are called with
> > > substream->lock spinlock already held by the PCM core, so they cannot
> > > be called at the same time as long as belonging to the same PCM
> > > substream instance.
> >
> > The driver writing howto says for hw_params, "is that this callback is
> > non-atomic (schedulable)."
> >
> > If it's non-atomic, that would mean to me that it can be called multiple
> > times at once, and at the same time as other callbacks.  But, you're saying
> > that's not the case?
> No, in that context, non-atomic means schedulable.  That is, the
> function can get scheduled safely.  It's outside the spinlock.

I see, it's not the normal definition of atomic:

I suggest something like "schedulable" or "process context".  When I see "X
is not atomic" I think that means I need to code the function to be

> About the concurrent access: since the PCM substream instance is
> exclusive, all PCM callbacks are also basically exclusive.  Even open
> and close are already protected via mutex in PCM core.  Thus they
> cannot be called simultaneously for the same substream instance.  (For
> different substreams, they can be called.)

Speaking of open, does one need to worry about the same pcm device being
opened multiple times?  I see code in the open callback of the bt87x driver
and the cx88-alsa driver that checks if the chip has already been opened
using atomic bit ops.  I'm guessing this is correct the bt87x driver, which
has two substreams of which only one can be used at one time.  But in the
cx88-alsa driver, which has only one substream, it is unnecessary.

I've figured out one of my problems, and it looks like it's not my fault.

I tried running arecord piped to aplay, both using the ca0106 driver, and
it works ok.  Very few overruns.  So this operation with this buffer size
_can_ be done.
arecord -v -D hw:0,0 -f DAT --buffer-size=512 | aplay -D hw:0,1 --buffer-size=512

So, I do the same thing with the device I'm working on, running arecord on
hw:1,0, but it doesn't work so well!  It's ok for a minute or two, but then
I start getting a lot of overruns.  I thought it was my driver, but then I
noticed something.

Once the overruns start, they were consistently about 3.5 seconds apart.
If I increased the arecord buffer size to 1024, they were 7 seconds apart,
at 2048 they were 13 seconds apart.

When I recorded and played back using the ca0106 card, both the ADC and DAC
were probably using the same master clock signal and the rates were locked.
But the other card was using a different clock and must have been producing
data faster than the ca0106 would play it.  After a while the pipe buffer
would fill up and arecord would block too long waiting for aplay to consume
its data, and there would be an overrun.  That empties the driver's pcm
buffer, but not the pipe between arecord and aplay.  So as soon as the pcm
buffer fills up, another overrun.  Each time the pcm buffer doubles in
size, it takes twice as long to fill up, and the time between overruns

More information about the Alsa-devel mailing list