All of lore.kernel.org
 help / color / mirror / Atom feed
* Races in alsa-lib with threads
@ 2012-11-10  2:03 Trent Piepho
  2012-11-10 13:53 ` Takashi Iwai
  0 siblings, 1 reply; 32+ messages in thread
From: Trent Piepho @ 2012-11-10  2:03 UTC (permalink / raw)
  To: alsa-devel

We've found a race with alsa-lib functions are called from multiple
threads.  I was under the impression that alsa-lib was supposed to be
thread safe.  Is this not the case and all alsa calls should be done
one from thread or protected by a mutex?

The race we found was in sync_ptr1() in pcm_hw.c.  This issues the
ioctl() to get the current hw ptr from the kernel and send the app ptr
to the kernel.  The communication is done by passing a pointer to
hw->sync_ptr, a field in the snd_pcm_hw_t structure for the pcm.  Any
thread calling sync_ptr1 will pass the same structure to the kernel.
This should be a red flag for a race, having two threads write to the
same data structure at the same time.

This function gets called by snd_pcm_writei(), as part of that
function getting the current hw pointer so it can calculate the avail
value.  And again when it actually writes data to commit the new app
pointer to the kernel.

It also gets called by snd_pcm_delay() if a rate plugin is used.
snd_pcm_rate_delay() will end up calling snd_pcm_hw_hwsync() and that
does a sync_ptr1() call.

So imaging two threads, one writing data and calling snd_pcm_writei()
and another calling snd_pcm_delay() as part of trying to sync audio
playback.  gstreamer does this!

The ioctl is handled by snd_pcm_sync_ptr() in pcm_native.c.  It gets
the stream lock while it reads/writes the various fields a sync struct
on the stack, then releases the lock and calls copy_to_user to write
the sync struct from its stack to userspace.

Here's how the race works.
Thread 1 calls snd_pcm_delay().
  sync_ptr1 is called
  snd_pcm_sync_ptr gets the lock, fills a struct with the current
data, releases the lock.  Does not call copy_to_user yet!
  Thread 2 runs!  It calls snd_pcm_writei(), actually writes data too
    It calls sync_ptr1() to update the app pointer with the new data and returns
    The snd_pcm_writei() call returns
  Thread 1 runs again, calls copy_to_user
    The copy_to_user writes the OLD struct that was prepared back on
the 3rd line into userspace
    The hw and app pointer values, as far as the userspace copy in
alsa-lib is concerned, have regressed to what they were before the
call to snd_pcm_writei()!

You get an audio stutter as the data written is overwritten by the
next write.  The race turns out to not be that unlikely.  The stream
lock is held and then released before calling copy_to_user.  When it's
released irqs are enabled.  If a period has elapsed while the lock was
held, the irq handle runs now, the elapsing period will wake anything
blocked in poll() waiting for space, which then probably gets to run
immediately since the schedule likes tasks that have been sleeping and
just woke, and the new task was probably blocked waiting to write data
so that's what it does as soon as it runs.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-10  2:03 Races in alsa-lib with threads Trent Piepho
@ 2012-11-10 13:53 ` Takashi Iwai
  2012-11-11 16:35   ` Jaroslav Kysela
  0 siblings, 1 reply; 32+ messages in thread
From: Takashi Iwai @ 2012-11-10 13:53 UTC (permalink / raw)
  To: Trent Piepho; +Cc: alsa-devel

At Fri, 9 Nov 2012 18:03:25 -0800,
Trent Piepho wrote:
> 
> We've found a race with alsa-lib functions are called from multiple
> threads.  I was under the impression that alsa-lib was supposed to be
> thread safe.  Is this not the case and all alsa calls should be done
> one from thread or protected by a mutex?

Yes.  alsa-lib isn't thread-safe.


Takashi

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-10 13:53 ` Takashi Iwai
@ 2012-11-11 16:35   ` Jaroslav Kysela
  2012-11-12 19:40     ` Rob Krakora
  0 siblings, 1 reply; 32+ messages in thread
From: Jaroslav Kysela @ 2012-11-11 16:35 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai, tpiepho

Date 10.11.2012 14:53, Takashi Iwai wrote:
> At Fri, 9 Nov 2012 18:03:25 -0800,
> Trent Piepho wrote:
>>
>> We've found a race with alsa-lib functions are called from multiple
>> threads.  I was under the impression that alsa-lib was supposed to be
>> thread safe.  Is this not the case and all alsa calls should be done
>> one from thread or protected by a mutex?
> 
> Yes.  alsa-lib isn't thread-safe.

The alsa-lib is designed to be thread safe but the calls for one handle
(PCM, control, rawmidi etc.) should be serialized using mutexes in apps.
Or basically, it's assumed that one thread will maintain one handle.

This should be documented somewhere.

					Jaroslav

-- 
Jaroslav Kysela <perex@perex.cz>
Linux Kernel Sound Maintainer
ALSA Project; Red Hat, Inc.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-11 16:35   ` Jaroslav Kysela
@ 2012-11-12 19:40     ` Rob Krakora
  2012-11-13  6:32       ` Takashi Iwai
  0 siblings, 1 reply; 32+ messages in thread
From: Rob Krakora @ 2012-11-12 19:40 UTC (permalink / raw)
  To: alsa-devel

Jaroslav Kysela <perex <at> perex.cz> writes:

> 
> Date 10.11.2012 14:53, Takashi Iwai wrote:
> > At Fri, 9 Nov 2012 18:03:25 -0800,
> > Trent Piepho wrote:
> >>
> >> We've found a race with alsa-lib functions are called from multiple
> >> threads.  I was under the impression that alsa-lib was supposed to be
> >> thread safe.  Is this not the case and all alsa calls should be done
> >> one from thread or protected by a mutex?
> > 
> > Yes.  alsa-lib isn't thread-safe.
> 
> The alsa-lib is designed to be thread safe but the calls for one handle
> (PCM, control, rawmidi etc.) should be serialized using mutexes in apps.
> Or basically, it's assumed that one thread will maintain one handle.
> 
> This should be documented somewhere.
> 
> 					Jaroslav
> 

Hi Jaroslav,

Would you be able to point me the the ALSA documentation that indicates the
stipulations on handle usage using multiple threads?  I cannot find it.

Best Regards,

Rob Krakora

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-12 19:40     ` Rob Krakora
@ 2012-11-13  6:32       ` Takashi Iwai
  2012-11-13  7:14         ` Trent Piepho
  0 siblings, 1 reply; 32+ messages in thread
From: Takashi Iwai @ 2012-11-13  6:32 UTC (permalink / raw)
  To: Rob Krakora; +Cc: alsa-devel

At Mon, 12 Nov 2012 19:40:42 +0000 (UTC),
Rob Krakora wrote:
> 
> Jaroslav Kysela <perex <at> perex.cz> writes:
> 
> > 
> > Date 10.11.2012 14:53, Takashi Iwai wrote:
> > > At Fri, 9 Nov 2012 18:03:25 -0800,
> > > Trent Piepho wrote:
> > >>
> > >> We've found a race with alsa-lib functions are called from multiple
> > >> threads.  I was under the impression that alsa-lib was supposed to be
> > >> thread safe.  Is this not the case and all alsa calls should be done
> > >> one from thread or protected by a mutex?
> > > 
> > > Yes.  alsa-lib isn't thread-safe.
> > 
> > The alsa-lib is designed to be thread safe but the calls for one handle
> > (PCM, control, rawmidi etc.) should be serialized using mutexes in apps.
> > Or basically, it's assumed that one thread will maintain one handle.
> > 
> > This should be documented somewhere.
> > 
> > 					Jaroslav
> > 
> 
> Hi Jaroslav,
> 
> Would you be able to point me the the ALSA documentation that indicates the
> stipulations on handle usage using multiple threads?  I cannot find it.

Think other way round:
The fact that it isn't documented means it's not safe to use in that
way :)


Takashi

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13  6:32       ` Takashi Iwai
@ 2012-11-13  7:14         ` Trent Piepho
  2012-11-13  7:30           ` Takashi Iwai
  0 siblings, 1 reply; 32+ messages in thread
From: Trent Piepho @ 2012-11-13  7:14 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Rob Krakora

On Tue, Nov 13, 2012 at 1:32 AM, Takashi Iwai <tiwai@suse.de> wrote:
> At Mon, 12 Nov 2012 19:40:42 +0000 (UTC),
> Rob Krakora wrote:
>> Would you be able to point me the the ALSA documentation that indicates the
>> stipulations on handle usage using multiple threads?  I cannot find it.
>
> Think other way round:
> The fact that it isn't documented means it's not safe to use in that
> way :)


The introduction on the alsa-project home page says, "SMP and
thread-safe design. "  Some people might misunderstand what
thread-safe means.  Maybe some clarification could be added.
"Different streams are SMP and thread-safe (calls for the same stream
must be serialized)."

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13  7:14         ` Trent Piepho
@ 2012-11-13  7:30           ` Takashi Iwai
       [not found]             ` <5175C6FEA820754B902FF6873E9285B00C985240@039-SN2MPN1-021.039d.mgd.msft.net>
  0 siblings, 1 reply; 32+ messages in thread
From: Takashi Iwai @ 2012-11-13  7:30 UTC (permalink / raw)
  To: Trent Piepho; +Cc: alsa-devel, Rob Krakora

At Tue, 13 Nov 2012 02:14:08 -0500,
Trent Piepho wrote:
> 
> On Tue, Nov 13, 2012 at 1:32 AM, Takashi Iwai <tiwai@suse.de> wrote:
> > At Mon, 12 Nov 2012 19:40:42 +0000 (UTC),
> > Rob Krakora wrote:
> >> Would you be able to point me the the ALSA documentation that indicates the
> >> stipulations on handle usage using multiple threads?  I cannot find it.
> >
> > Think other way round:
> > The fact that it isn't documented means it's not safe to use in that
> > way :)
> 
> 
> The introduction on the alsa-project home page says, "SMP and
> thread-safe design. "  Some people might misunderstand what
> thread-safe means.  Maybe some clarification could be added.
> "Different streams are SMP and thread-safe (calls for the same stream
> must be serialized)."

Yeah this should be corrected.  SMP things are just about the kernel
side at that time.

It's a Wiki, feel free to correct / improve the text.


Takashi

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
       [not found]             ` <5175C6FEA820754B902FF6873E9285B00C985240@039-SN2MPN1-021.039d.mgd.msft.net>
@ 2012-11-13 13:47               ` Krakora Robert-B42341
  2012-11-13 13:50               ` Takashi Iwai
  1 sibling, 0 replies; 32+ messages in thread
From: Krakora Robert-B42341 @ 2012-11-13 13:47 UTC (permalink / raw)
  To: Takashi Iwai, Trent Piepho; +Cc: Huolin.Yang, alsa-devel

> From: Takashi Iwai [tiwai@suse.de]
> Sent: Tuesday, November 13, 2012 2:30 AM
> To: Trent Piepho
> Cc: Krakora Robert-B42341; alsa-devel@alsa-project.org
> Subject: Re: [alsa-devel] Races in alsa-lib with threads
>
> At Tue, 13 Nov 2012 02:14:08 -0500,
> Trent Piepho wrote:
> >
> > On Tue, Nov 13, 2012 at 1:32 AM, Takashi Iwai <tiwai@suse.de> wrote:
> > > At Mon, 12 Nov 2012 19:40:42 +0000 (UTC),
> > > Rob Krakora wrote:
> > >> Would you be able to point me the the ALSA documentation that indicates the
> > >> stipulations on handle usage using multiple threads?  I cannot find it.
> > >
> > > Think other way round:
> > > The fact that it isn't documented means it's not safe to use in that
> > > way :)
> >
> >
> > The introduction on the alsa-project home page says, "SMP and
> > thread-safe design. "  Some people might misunderstand what
> > thread-safe means.  Maybe some clarification could be added.
> > "Different streams are SMP and thread-safe (calls for the same stream
> > must be serialized)."
>
> Yeah this should be corrected.  SMP things are just about the kernel
> side at that time.
>
> It's a Wiki, feel free to correct / improve the text.
>
>
> Takashi

Hi Takashi,

The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact other functionality within ALSA Lib.

Best Regards,

Rob Krakora

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
       [not found]             ` <5175C6FEA820754B902FF6873E9285B00C985240@039-SN2MPN1-021.039d.mgd.msft.net>
  2012-11-13 13:47               ` Krakora Robert-B42341
@ 2012-11-13 13:50               ` Takashi Iwai
  2012-11-13 14:04                 ` Krakora Robert-B42341
                                   ` (3 more replies)
  1 sibling, 4 replies; 32+ messages in thread
From: Takashi Iwai @ 2012-11-13 13:50 UTC (permalink / raw)
  To: Krakora Robert-B42341; +Cc: alsa-devel, Trent Piepho

At Tue, 13 Nov 2012 13:39:24 +0000,
Krakora Robert-B42341 wrote:
> 
> [1  <text/plain; us-ascii (quoted-printable)>]
> > From: Takashi Iwai [tiwai@suse.de]
> > Sent: Tuesday, November 13, 2012 2:30 AM
> > To: Trent Piepho
> > Cc: Krakora Robert-B42341; alsa-devel@alsa-project.org
> > Subject: Re: [alsa-devel] Races in alsa-lib with threads
> >
> > At Tue, 13 Nov 2012 02:14:08 -0500,
> > Trent Piepho wrote:
> > >
> > > On Tue, Nov 13, 2012 at 1:32 AM, Takashi Iwai <tiwai@suse.de> wrote:
> > > > At Mon, 12 Nov 2012 19:40:42 +0000 (UTC),
> > > > Rob Krakora wrote:
> > > >> Would you be able to point me the the ALSA documentation that indicates the
> > > >> stipulations on handle usage using multiple threads?  I cannot find it.
> > > >
> > > > Think other way round:
> > > > The fact that it isn't documented means it's not safe to use in that
> > > > way :)
> > >
> > >
> > > The introduction on the alsa-project home page says, "SMP and
> > > thread-safe design. "  Some people might misunderstand what
> > > thread-safe means.  Maybe some clarification could be added.
> > > "Different streams are SMP and thread-safe (calls for the same stream
> > > must be serialized)."
> >
> > Yeah this should be corrected.  SMP things are just about the kernel
> > side at that time.
> > 
> > It's a Wiki, feel free to correct / improve the text.
> >
> >
> > Takashi
> 
> Hi Takashi,
> 
> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact other functionality within ALSA Lib.

No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
stuff.

We already have a few places, yes, but they are exceptional (mostly
for funky rarely used plugins that we can drop or mixer codes that
are no hot path).


Takashi

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 13:50               ` Takashi Iwai
@ 2012-11-13 14:04                 ` Krakora Robert-B42341
  2012-11-13 14:18                   ` Takashi Iwai
  2012-11-13 14:08                 ` Jaroslav Kysela
                                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 32+ messages in thread
From: Krakora Robert-B42341 @ 2012-11-13 14:04 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Huolin.Yang, alsa-devel, Trent Piepho

>From: Takashi Iwai [tiwai@suse.de]
>Sent: Tuesday, November 13, 2012 8:50 AM
>To: Krakora Robert-B42341
>Cc: Trent Piepho; alsa-devel@alsa-project.org
>Subject: Re: [alsa-devel] Races in alsa-lib with threads
>
>At Tue, 13 Nov 2012 13:39:24 +0000,
>Krakora Robert-B42341 wrote:
>>
>> [1  <text/plain; us-ascii (quoted-printable)>]
>> > From: Takashi Iwai [tiwai@suse.de]
>> > Sent: Tuesday, November 13, 2012 2:30 AM
>> > To: Trent Piepho
>> > Cc: Krakora Robert-B42341; alsa-devel@alsa-project.org
>> > Subject: Re: [alsa-devel] Races in alsa-lib with threads
>> >
>> > At Tue, 13 Nov 2012 02:14:08 -0500,
>> > Trent Piepho wrote:
>> > >
>> > > On Tue, Nov 13, 2012 at 1:32 AM, Takashi Iwai <tiwai@suse.de> wrote:
>> > > > At Mon, 12 Nov 2012 19:40:42 +0000 (UTC),
>> > > > Rob Krakora wrote:
>> > > >> Would you be able to point me the the ALSA documentation that indicates the
>> > > >> stipulations on handle usage using multiple threads?  I cannot find it.
>> > > >
>> > > > Think other way round:
>> > > > The fact that it isn't documented means it's not safe to use in that
>> > > > way :)
>> > >
>> > >
>> > > The introduction on the alsa-project home page says, "SMP and
>> > > thread-safe design. "  Some people might misunderstand what
>> > > thread-safe means.  Maybe some clarification could be added.
>> > > "Different streams are SMP and thread-safe (calls for the same stream
>> > > must be serialized)."
>> >
>> > Yeah this should be corrected.  SMP things are just about the kernel
>> > side at that time.
>> >
>> > It's a Wiki, feel free to correct / improve the text.
>> >
>> >
>> > Takashi
>>
>> Hi Takashi,
>>
>> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted >by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact >other functionality within ALSA Lib.
>
>No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
>stuff.
>
>We already have a few places, yes, but they are exceptional (mostly
>for funky rarely used plugins that we can drop or mixer codes that
>are no hot path).
>
>Takashi

Hi Takashi,

OK, but it sure seems as though the better fix would be in ALSA Lib (but then ALSA Lib assumes a great deal of risk unless it is re-architected for thread safety).  However, you have an already established paradigm so I will see what I can do in the GStreamer ALSA Sink plugin.

Best Regards,

Rob Krakora

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 13:50               ` Takashi Iwai
  2012-11-13 14:04                 ` Krakora Robert-B42341
@ 2012-11-13 14:08                 ` Jaroslav Kysela
  2012-11-13 14:15                   ` Krakora Robert-B42341
  2012-11-13 14:19                   ` Takashi Iwai
  2012-11-13 14:26                 ` Krakora Robert-B42341
  2012-11-13 19:41                 ` Trent Piepho
  3 siblings, 2 replies; 32+ messages in thread
From: Jaroslav Kysela @ 2012-11-13 14:08 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Trent Piepho, Krakora Robert-B42341

Date 13.11.2012 14:50, Takashi Iwai wrote:
> At Tue, 13 Nov 2012 13:39:24 +0000, Krakora Robert-B42341 wrote:
>> 
>> [1  <text/plain; us-ascii (quoted-printable)>]
>>> From: Takashi Iwai [tiwai@suse.de] Sent: Tuesday, November 13,
>>> 2012 2:30 AM To: Trent Piepho Cc: Krakora Robert-B42341;
>>> alsa-devel@alsa-project.org Subject: Re: [alsa-devel] Races in
>>> alsa-lib with threads
>>> 
>>> At Tue, 13 Nov 2012 02:14:08 -0500, Trent Piepho wrote:
>>>> 
>>>> On Tue, Nov 13, 2012 at 1:32 AM, Takashi Iwai <tiwai@suse.de>
>>>> wrote:
>>>>> At Mon, 12 Nov 2012 19:40:42 +0000 (UTC), Rob Krakora wrote:
>>>>>> Would you be able to point me the the ALSA documentation
>>>>>> that indicates the stipulations on handle usage using
>>>>>> multiple threads?  I cannot find it.
>>>>> 
>>>>> Think other way round: The fact that it isn't documented
>>>>> means it's not safe to use in that way :)
>>>> 
>>>> 
>>>> The introduction on the alsa-project home page says, "SMP and 
>>>> thread-safe design. "  Some people might misunderstand what 
>>>> thread-safe means.  Maybe some clarification could be added. 
>>>> "Different streams are SMP and thread-safe (calls for the same
>>>> stream must be serialized)."
>>> 
>>> Yeah this should be corrected.  SMP things are just about the
>>> kernel side at that time.
>>> 
>>> It's a Wiki, feel free to correct / improve the text.
>>> 
>>> 
>>> Takashi
>> 
>> Hi Takashi,
>> 
>> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib
>> assumes that it is thread safe.  The fix crafted by one of Trent's
>> colleagues (attached) seems to be the way to go.  However, I don't
>> know how it would impact other functionality within ALSA Lib.
> 
> No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM 
> stuff.
> 
> We already have a few places, yes, but they are exceptional (mostly 
> for funky rarely used plugins that we can drop or mixer codes that 
> are no hot path).

I tried to put notes on the ALSA Wiki, please, extend / fix / review.

http://www.alsa-project.org/main/index.php/SMP_Design

					Jaroslav

-- 
Jaroslav Kysela <perex@perex.cz>
Linux Kernel Sound Maintainer
ALSA Project; Red Hat, Inc.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 14:08                 ` Jaroslav Kysela
@ 2012-11-13 14:15                   ` Krakora Robert-B42341
  2012-11-13 14:19                   ` Takashi Iwai
  1 sibling, 0 replies; 32+ messages in thread
From: Krakora Robert-B42341 @ 2012-11-13 14:15 UTC (permalink / raw)
  To: Jaroslav Kysela, Takashi Iwai; +Cc: alsa-devel, Trent Piepho

From: Jaroslav Kysela [perex@perex.cz]
Sent: Tuesday, November 13, 2012 9:08 AM
To: Takashi Iwai
Cc: Krakora Robert-B42341; alsa-devel@alsa-project.org; Trent Piepho
Subject: Re: [alsa-devel] Races in alsa-lib with threads

Date 13.11.2012 14:50, Takashi Iwai wrote:
> At Tue, 13 Nov 2012 13:39:24 +0000, Krakora Robert-B42341 wrote:
>>
>> [1  <text/plain; us-ascii (quoted-printable)>]
>>> From: Takashi Iwai [tiwai@suse.de] Sent: Tuesday, November 13,
>>> 2012 2:30 AM To: Trent Piepho Cc: Krakora Robert-B42341;
>>> alsa-devel@alsa-project.org Subject: Re: [alsa-devel] Races in
>>> alsa-lib with threads
>>>
>>> At Tue, 13 Nov 2012 02:14:08 -0500, Trent Piepho wrote:
>>>>
>>>> On Tue, Nov 13, 2012 at 1:32 AM, Takashi Iwai <tiwai@suse.de>
>>>> wrote:
>>>>> At Mon, 12 Nov 2012 19:40:42 +0000 (UTC), Rob Krakora wrote:
>>>>>> Would you be able to point me the the ALSA documentation
>>>>>> that indicates the stipulations on handle usage using
>>>>>> multiple threads?  I cannot find it.
>>>>>
>>>>> Think other way round: The fact that it isn't documented
>>>>> means it's not safe to use in that way :)
>>>>
>>>>
>>>> The introduction on the alsa-project home page says, "SMP and
>>>> thread-safe design. "  Some people might misunderstand what
>>>> thread-safe means.  Maybe some clarification could be added.
>>>> "Different streams are SMP and thread-safe (calls for the same
>>>> stream must be serialized)."
>>>
>>> Yeah this should be corrected.  SMP things are just about the
>>> kernel side at that time.
>>>
>>> It's a Wiki, feel free to correct / improve the text.
>>>
>>>
>>> Takashi
>>
>> Hi Takashi,
>>
>> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib
>> assumes that it is thread safe.  The fix crafted by one of Trent's
>> colleagues (attached) seems to be the way to go.  However, I don't
>> know how it would impact other functionality within ALSA Lib.
>
> No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
> stuff.
>
> We already have a few places, yes, but they are exceptional (mostly
> for funky rarely used plugins that we can drop or mixer codes that
> are no hot path).

I tried to put notes on the ALSA Wiki, please, extend / fix / review.

http://www.alsa-project.org/main/index.php/SMP_Design

                                        Jaroslav

--
Jaroslav Kysela <perex@perex.cz>
Linux Kernel Sound Maintainer
ALSA Project; Red Hat, Inc.

Hi Jaroslav,

Looks good, except I think the text in the link on the main page should be changed from "see these notes" to "PLEASE READ FIRST" in all caps for emphasis.

Best Regards,

Rob Krakora

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 14:04                 ` Krakora Robert-B42341
@ 2012-11-13 14:18                   ` Takashi Iwai
  0 siblings, 0 replies; 32+ messages in thread
From: Takashi Iwai @ 2012-11-13 14:18 UTC (permalink / raw)
  To: Krakora Robert-B42341; +Cc: Huolin.Yang, alsa-devel, Trent Piepho

At Tue, 13 Nov 2012 14:04:22 +0000,
Krakora Robert-B42341 wrote:
> 
> >From: Takashi Iwai [tiwai@suse.de]
> >Sent: Tuesday, November 13, 2012 8:50 AM
> >To: Krakora Robert-B42341
> >Cc: Trent Piepho; alsa-devel@alsa-project.org
> >Subject: Re: [alsa-devel] Races in alsa-lib with threads
> >
> >At Tue, 13 Nov 2012 13:39:24 +0000,
> >Krakora Robert-B42341 wrote:
> >>
> >> [1  <text/plain; us-ascii (quoted-printable)>]
> >> > From: Takashi Iwai [tiwai@suse.de]
> >> > Sent: Tuesday, November 13, 2012 2:30 AM
> >> > To: Trent Piepho
> >> > Cc: Krakora Robert-B42341; alsa-devel@alsa-project.org
> >> > Subject: Re: [alsa-devel] Races in alsa-lib with threads
> >> >
> >> > At Tue, 13 Nov 2012 02:14:08 -0500,
> >> > Trent Piepho wrote:
> >> > >
> >> > > On Tue, Nov 13, 2012 at 1:32 AM, Takashi Iwai <tiwai@suse.de> wrote:
> >> > > > At Mon, 12 Nov 2012 19:40:42 +0000 (UTC),
> >> > > > Rob Krakora wrote:
> >> > > >> Would you be able to point me the the ALSA documentation that indicates the
> >> > > >> stipulations on handle usage using multiple threads?  I cannot find it.
> >> > > >
> >> > > > Think other way round:
> >> > > > The fact that it isn't documented means it's not safe to use in that
> >> > > > way :)
> >> > >
> >> > >
> >> > > The introduction on the alsa-project home page says, "SMP and
> >> > > thread-safe design. "  Some people might misunderstand what
> >> > > thread-safe means.  Maybe some clarification could be added.
> >> > > "Different streams are SMP and thread-safe (calls for the same stream
> >> > > must be serialized)."
> >> >
> >> > Yeah this should be corrected.  SMP things are just about the kernel
> >> > side at that time.
> >> >
> >> > It's a Wiki, feel free to correct / improve the text.
> >> >
> >> >
> >> > Takashi
> >>
> >> Hi Takashi,
> >>
> >> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted >by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact >other functionality within ALSA Lib.
> >
> >No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
> >stuff.
> >
> >We already have a few places, yes, but they are exceptional (mostly
> >for funky rarely used plugins that we can drop or mixer codes that
> >are no hot path).
> >
> >Takashi
> 
> Hi Takashi,
> 
> OK, but it sure seems as though the better fix would be in ALSA Lib
> (but then ALSA Lib assumes a great deal of risk unless it is
> re-architected for thread safety).

Yeah, introducing a thread-safe requires some fundamental redesign.
Otherwise we need pthread lock which is always risky to break
something.

>  However, you have an already established paradigm so I will see
>  what I can do in the GStreamer ALSA Sink plugin.

Thanks!


Takashi

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 14:08                 ` Jaroslav Kysela
  2012-11-13 14:15                   ` Krakora Robert-B42341
@ 2012-11-13 14:19                   ` Takashi Iwai
  1 sibling, 0 replies; 32+ messages in thread
From: Takashi Iwai @ 2012-11-13 14:19 UTC (permalink / raw)
  To: Jaroslav Kysela; +Cc: alsa-devel, Trent Piepho, Krakora Robert-B42341

At Tue, 13 Nov 2012 15:08:29 +0100,
Jaroslav Kysela wrote:
> 
> Date 13.11.2012 14:50, Takashi Iwai wrote:
> > At Tue, 13 Nov 2012 13:39:24 +0000, Krakora Robert-B42341 wrote:
> >> 
> >> [1  <text/plain; us-ascii (quoted-printable)>]
> >>> From: Takashi Iwai [tiwai@suse.de] Sent: Tuesday, November 13,
> >>> 2012 2:30 AM To: Trent Piepho Cc: Krakora Robert-B42341;
> >>> alsa-devel@alsa-project.org Subject: Re: [alsa-devel] Races in
> >>> alsa-lib with threads
> >>> 
> >>> At Tue, 13 Nov 2012 02:14:08 -0500, Trent Piepho wrote:
> >>>> 
> >>>> On Tue, Nov 13, 2012 at 1:32 AM, Takashi Iwai <tiwai@suse.de>
> >>>> wrote:
> >>>>> At Mon, 12 Nov 2012 19:40:42 +0000 (UTC), Rob Krakora wrote:
> >>>>>> Would you be able to point me the the ALSA documentation
> >>>>>> that indicates the stipulations on handle usage using
> >>>>>> multiple threads?  I cannot find it.
> >>>>> 
> >>>>> Think other way round: The fact that it isn't documented
> >>>>> means it's not safe to use in that way :)
> >>>> 
> >>>> 
> >>>> The introduction on the alsa-project home page says, "SMP and 
> >>>> thread-safe design. "  Some people might misunderstand what 
> >>>> thread-safe means.  Maybe some clarification could be added. 
> >>>> "Different streams are SMP and thread-safe (calls for the same
> >>>> stream must be serialized)."
> >>> 
> >>> Yeah this should be corrected.  SMP things are just about the
> >>> kernel side at that time.
> >>> 
> >>> It's a Wiki, feel free to correct / improve the text.
> >>> 
> >>> 
> >>> Takashi
> >> 
> >> Hi Takashi,
> >> 
> >> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib
> >> assumes that it is thread safe.  The fix crafted by one of Trent's
> >> colleagues (attached) seems to be the way to go.  However, I don't
> >> know how it would impact other functionality within ALSA Lib.
> > 
> > No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM 
> > stuff.
> > 
> > We already have a few places, yes, but they are exceptional (mostly 
> > for funky rarely used plugins that we can drop or mixer codes that 
> > are no hot path).
> 
> I tried to put notes on the ALSA Wiki, please, extend / fix / review.
> 
> http://www.alsa-project.org/main/index.php/SMP_Design

This looks much clearer now.  Thanks!


Takashi

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 13:50               ` Takashi Iwai
  2012-11-13 14:04                 ` Krakora Robert-B42341
  2012-11-13 14:08                 ` Jaroslav Kysela
@ 2012-11-13 14:26                 ` Krakora Robert-B42341
  2012-11-13 19:41                 ` Trent Piepho
  3 siblings, 0 replies; 32+ messages in thread
From: Krakora Robert-B42341 @ 2012-11-13 14:26 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: kevin.w.kaster, Huolin.Yang, alsa-devel, Trent Piepho

From: Takashi Iwai [tiwai@suse.de]
Sent: Tuesday, November 13, 2012 8:50 AM
To: Krakora Robert-B42341
Cc: Trent Piepho; alsa-devel@alsa-project.org
Subject: Re: [alsa-devel] Races in alsa-lib with threads

At Tue, 13 Nov 2012 13:39:24 +0000,
Krakora Robert-B42341 wrote:
>
> [1  <text/plain; us-ascii (quoted-printable)>]
> > From: Takashi Iwai [tiwai@suse.de]
> > Sent: Tuesday, November 13, 2012 2:30 AM
> > To: Trent Piepho
> > Cc: Krakora Robert-B42341; alsa-devel@alsa-project.org
> > Subject: Re: [alsa-devel] Races in alsa-lib with threads
> >
> > At Tue, 13 Nov 2012 02:14:08 -0500,
> > Trent Piepho wrote:
> > >
> > > On Tue, Nov 13, 2012 at 1:32 AM, Takashi Iwai <tiwai@suse.de> wrote:
> > > > At Mon, 12 Nov 2012 19:40:42 +0000 (UTC),
> > > > Rob Krakora wrote:
> > > >> Would you be able to point me the the ALSA documentation that indicates the
> > > >> stipulations on handle usage using multiple threads?  I cannot find it.
> > > >
> > > > Think other way round:
> > > > The fact that it isn't documented means it's not safe to use in that
> > > > way :)
> > >
> > >
> > > The introduction on the alsa-project home page says, "SMP and
> > > thread-safe design. "  Some people might misunderstand what
> > > thread-safe means.  Maybe some clarification could be added.
> > > "Different streams are SMP and thread-safe (calls for the same stream
> > > must be serialized)."
> >
> > Yeah this should be corrected.  SMP things are just about the kernel
> > side at that time.
> >
> > It's a Wiki, feel free to correct / improve the text.
> >
> >
> > Takashi
>
> Hi Takashi,
>
> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact other functionality within ALSA Lib.

No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
stuff.

We already have a few places, yes, but they are exceptional (mostly
for funky rarely used plugins that we can drop or mixer codes that
are no hot path).


Takashi

Hi Takashi,

A colleague found this from two years ago:  http://mailman.alsa-project.org/pipermail/alsa-devel/2010-June/028347.html.

IMHO, it seems trivial and harmless to serialize appl.ptr updates with mutexes unless there is a potential for deadlock or other possible race conditions in the affected ALSA Lib functions.  I know it breaks the paradigm, but you can see how snd_pcm_delay() function can lead a developer to believe that it can be called on a different thread time from snd_pcm_writei().

Best Regards,

Rob Krakora

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 13:50               ` Takashi Iwai
                                   ` (2 preceding siblings ...)
  2012-11-13 14:26                 ` Krakora Robert-B42341
@ 2012-11-13 19:41                 ` Trent Piepho
  2012-11-13 20:23                   ` Clemens Ladisch
                                     ` (3 more replies)
  3 siblings, 4 replies; 32+ messages in thread
From: Trent Piepho @ 2012-11-13 19:41 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Krakora Robert-B42341

On Tue, Nov 13, 2012 at 8:50 AM, Takashi Iwai <tiwai@suse.de> wrote:
> At Tue, 13 Nov 2012 13:39:24 +0000,
> Krakora Robert-B42341 wrote:
>> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact other functionality within ALSA Lib.
>
> No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
> stuff.
>

The problem with introduction serialization outside alsa-lib is that
you must now serialize entire ALSA calls.  The locks must be held for
far too long.

Consider snd_pcm_writei(), most of the time is usually spent blocked
waiting for a period to elapse.  It is perfectly ok to call
snd_pcm_delay() during this time.  But if one isn't allowed to make
any other pcm calls during snd_pcm_writei() then this can't be done.

It's a pretty big problem.  Most code using blocking mode is going to
write another period as soon as the writei call returns from the last
write.  It will spend almost all its time inside snd_pcm_writei() and
thus will always be holding the app's pcm stream lock.  As soon as it
releases the lock it grabs it again for the next write.  Another
thread trying to call snd_pcm_delay() will virtually NEVER get a
chance.  Not only is it unnecessary stopped from getting the delay
while another thread is blocked inside writei(), but it won't get a
chance to call it between writei() calls either.

But there doesn't need to be a conflict, since the actual critical
section that needs locking is very small, far smaller than the time
spent sleeping inside writei() or wait().  How can just the critical
section be protected without placing the locking inside alsa-lib?

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 19:41                 ` Trent Piepho
@ 2012-11-13 20:23                   ` Clemens Ladisch
  2012-11-13 20:36                     ` Trent Piepho
  2012-11-13 20:29                   ` Takashi Iwai
                                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 32+ messages in thread
From: Clemens Ladisch @ 2012-11-13 20:23 UTC (permalink / raw)
  To: Trent Piepho; +Cc: Takashi Iwai, alsa-devel, Krakora Robert-B42341

Trent Piepho wrote:
> Consider snd_pcm_writei(), most of the time is usually spent blocked
> waiting for a period to elapse.  It is perfectly ok to call
> snd_pcm_delay() during this time.  But if one isn't allowed to make
> any other pcm calls during snd_pcm_writei() then this can't be done.

Then use non-blocking mode.  Blocking mode is suitable only for
applications that do not want to access the device while waiting.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 19:41                 ` Trent Piepho
  2012-11-13 20:23                   ` Clemens Ladisch
@ 2012-11-13 20:29                   ` Takashi Iwai
  2012-11-13 20:55                     ` Krakora Robert-B42341
  2012-11-13 20:52                   ` Krakora Robert-B42341
  2012-11-14  8:02                   ` David Henningsson
  3 siblings, 1 reply; 32+ messages in thread
From: Takashi Iwai @ 2012-11-13 20:29 UTC (permalink / raw)
  To: Trent Piepho; +Cc: alsa-devel, Krakora Robert-B42341

At Tue, 13 Nov 2012 14:41:40 -0500,
Trent Piepho wrote:
> 
> On Tue, Nov 13, 2012 at 8:50 AM, Takashi Iwai <tiwai@suse.de> wrote:
> > At Tue, 13 Nov 2012 13:39:24 +0000,
> > Krakora Robert-B42341 wrote:
> >> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact other functionality within ALSA Lib.
> >
> > No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
> > stuff.
> >
> 
> The problem with introduction serialization outside alsa-lib is that
> you must now serialize entire ALSA calls.  The locks must be held for
> far too long.
> 
> Consider snd_pcm_writei(), most of the time is usually spent blocked
> waiting for a period to elapse.  It is perfectly ok to call
> snd_pcm_delay() during this time.  But if one isn't allowed to make
> any other pcm calls during snd_pcm_writei() then this can't be done.
> 
> It's a pretty big problem.  Most code using blocking mode is going to
> write another period as soon as the writei call returns from the last
> write.  It will spend almost all its time inside snd_pcm_writei() and
> thus will always be holding the app's pcm stream lock.  As soon as it
> releases the lock it grabs it again for the next write.  Another
> thread trying to call snd_pcm_delay() will virtually NEVER get a
> chance.  Not only is it unnecessary stopped from getting the delay
> while another thread is blocked inside writei(), but it won't get a
> chance to call it between writei() calls either.
> 
> But there doesn't need to be a conflict, since the actual critical
> section that needs locking is very small, far smaller than the time
> spent sleeping inside writei() or wait().  How can just the critical
> section be protected without placing the locking inside alsa-lib?

Well, in general it's no good idea to use a blocking write for
multi-thread programs.  Most of codes I know use a direct poll() call
for a better control.  The blocking mode is basically for dumb program
that doesn't need a control.

Though, I see your point, too.  Of course it'd be better if there is
an atomic snd_pcm_delay() call.  I think it's possible to give a
consistent value without locking.  Here I meant a value that doesn't
express the exact position of the very current time, but at least a
position that is being processed.  It'll likely end up calling
snd_pcm_mmap_avail(), and this won't involve with the sync / update
procedure.

Well, just a thought, for now.


Takashi

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 20:23                   ` Clemens Ladisch
@ 2012-11-13 20:36                     ` Trent Piepho
  0 siblings, 0 replies; 32+ messages in thread
From: Trent Piepho @ 2012-11-13 20:36 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: Takashi Iwai, alsa-devel, Krakora Robert-B42341

On Tue, Nov 13, 2012 at 3:23 PM, Clemens Ladisch <clemens@ladisch.de> wrote:
> Trent Piepho wrote:
>> Consider snd_pcm_writei(), most of the time is usually spent blocked
>> waiting for a period to elapse.  It is perfectly ok to call
>> snd_pcm_delay() during this time.  But if one isn't allowed to make
>> any other pcm calls during snd_pcm_writei() then this can't be done.
>
> Then use non-blocking mode.  Blocking mode is suitable only for
> applications that do not want to access the device while waiting.

So you get the same problem with snd_pcm_wait().  Or snd_pcm_drain().
Any alsa-lib function than can block will exclude other threads from
alsa-lib for much longer than necessary.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 19:41                 ` Trent Piepho
  2012-11-13 20:23                   ` Clemens Ladisch
  2012-11-13 20:29                   ` Takashi Iwai
@ 2012-11-13 20:52                   ` Krakora Robert-B42341
  2012-11-14  8:02                   ` David Henningsson
  3 siblings, 0 replies; 32+ messages in thread
From: Krakora Robert-B42341 @ 2012-11-13 20:52 UTC (permalink / raw)
  To: Trent Piepho, Takashi Iwai; +Cc: alsa-devel

From: Trent Piepho [tpiepho@gmail.com]
Sent: Tuesday, November 13, 2012 2:41 PM
To: Takashi Iwai
Cc: Krakora Robert-B42341; alsa-devel@alsa-project.org
Subject: Re: [alsa-devel] Races in alsa-lib with threads

On Tue, Nov 13, 2012 at 8:50 AM, Takashi Iwai <tiwai@suse.de> wrote:
> At Tue, 13 Nov 2012 13:39:24 +0000,
> Krakora Robert-B42341 wrote:
>> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact other functionality within ALSA Lib.
>
> No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
> stuff.
>

The problem with introduction serialization outside alsa-lib is that
you must now serialize entire ALSA calls.  The locks must be held for
far too long.

Consider snd_pcm_writei(), most of the time is usually spent blocked
waiting for a period to elapse.  It is perfectly ok to call
snd_pcm_delay() during this time.  But if one isn't allowed to make
any other pcm calls during snd_pcm_writei() then this can't be done.

It's a pretty big problem.  Most code using blocking mode is going to
write another period as soon as the writei call returns from the last
write.  It will spend almost all its time inside snd_pcm_writei() and
thus will always be holding the app's pcm stream lock.  As soon as it
releases the lock it grabs it again for the next write.  Another
thread trying to call snd_pcm_delay() will virtually NEVER get a
chance.  Not only is it unnecessary stopped from getting the delay
while another thread is blocked inside writei(), but it won't get a
chance to call it between writei() calls either.

But there doesn't need to be a conflict, since the actual critical
section that needs locking is very small, far smaller than the time
spent sleeping inside writei() or wait().  How can just the critical
section be protected without placing the locking inside alsa-lib?



I don't think it can.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 20:29                   ` Takashi Iwai
@ 2012-11-13 20:55                     ` Krakora Robert-B42341
  2012-11-13 21:11                       ` Krakora Robert-B42341
  0 siblings, 1 reply; 32+ messages in thread
From: Krakora Robert-B42341 @ 2012-11-13 20:55 UTC (permalink / raw)
  To: Takashi Iwai, Trent Piepho; +Cc: alsa-devel

At Tue, 13 Nov 2012 14:41:40 -0500,
Trent Piepho wrote:
>
> On Tue, Nov 13, 2012 at 8:50 AM, Takashi Iwai <tiwai@suse.de> wrote:
> > At Tue, 13 Nov 2012 13:39:24 +0000,
> > Krakora Robert-B42341 wrote:
> >> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact other functionality within ALSA Lib.
> >
> > No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
> > stuff.
> >
>
> The problem with introduction serialization outside alsa-lib is that
> you must now serialize entire ALSA calls.  The locks must be held for
> far too long.
>
> Consider snd_pcm_writei(), most of the time is usually spent blocked
> waiting for a period to elapse.  It is perfectly ok to call
> snd_pcm_delay() during this time.  But if one isn't allowed to make
> any other pcm calls during snd_pcm_writei() then this can't be done.
>
> It's a pretty big problem.  Most code using blocking mode is going to
> write another period as soon as the writei call returns from the last
> write.  It will spend almost all its time inside snd_pcm_writei() and
> thus will always be holding the app's pcm stream lock.  As soon as it
> releases the lock it grabs it again for the next write.  Another
> thread trying to call snd_pcm_delay() will virtually NEVER get a
> chance.  Not only is it unnecessary stopped from getting the delay
> while another thread is blocked inside writei(), but it won't get a
> chance to call it between writei() calls either.
>
> But there doesn't need to be a conflict, since the actual critical
> section that needs locking is very small, far smaller than the time
> spent sleeping inside writei() or wait().  How can just the critical
> section be protected without placing the locking inside alsa-lib?

Well, in general it's no good idea to use a blocking write for
multi-thread programs.  Most of codes I know use a direct poll() call
for a better control.  The blocking mode is basically for dumb program
that doesn't need a control.

Though, I see your point, too.  Of course it'd be better if there is
an atomic snd_pcm_delay() call.  I think it's possible to give a
consistent value without locking.  Here I meant a value that doesn't
express the exact position of the very current time, but at least a
position that is being processed.  It'll likely end up calling
snd_pcm_mmap_avail(), and this won't involve with the sync / update
procedure.

Well, just a thought, for now.


Takashi


So, the "dumb program" is the GStreamer ALSA Sink plugin.  What does an ALSA "poll" example look like?

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 20:55                     ` Krakora Robert-B42341
@ 2012-11-13 21:11                       ` Krakora Robert-B42341
  0 siblings, 0 replies; 32+ messages in thread
From: Krakora Robert-B42341 @ 2012-11-13 21:11 UTC (permalink / raw)
  To: Takashi Iwai, Trent Piepho; +Cc: alsa-devel

snd_pcm_poll instead of snd_pcm_delay?
________________________________________
From: Krakora Robert-B42341
Sent: Tuesday, November 13, 2012 3:55 PM
To: Takashi Iwai; Trent Piepho
Cc: alsa-devel@alsa-project.org
Subject: RE: [alsa-devel] Races in alsa-lib with threads

At Tue, 13 Nov 2012 14:41:40 -0500,
Trent Piepho wrote:
>
> On Tue, Nov 13, 2012 at 8:50 AM, Takashi Iwai <tiwai@suse.de> wrote:
> > At Tue, 13 Nov 2012 13:39:24 +0000,
> > Krakora Robert-B42341 wrote:
> >> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact other functionality within ALSA Lib.
> >
> > No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
> > stuff.
> >
>
> The problem with introduction serialization outside alsa-lib is that
> you must now serialize entire ALSA calls.  The locks must be held for
> far too long.
>
> Consider snd_pcm_writei(), most of the time is usually spent blocked
> waiting for a period to elapse.  It is perfectly ok to call
> snd_pcm_delay() during this time.  But if one isn't allowed to make
> any other pcm calls during snd_pcm_writei() then this can't be done.
>
> It's a pretty big problem.  Most code using blocking mode is going to
> write another period as soon as the writei call returns from the last
> write.  It will spend almost all its time inside snd_pcm_writei() and
> thus will always be holding the app's pcm stream lock.  As soon as it
> releases the lock it grabs it again for the next write.  Another
> thread trying to call snd_pcm_delay() will virtually NEVER get a
> chance.  Not only is it unnecessary stopped from getting the delay
> while another thread is blocked inside writei(), but it won't get a
> chance to call it between writei() calls either.
>
> But there doesn't need to be a conflict, since the actual critical
> section that needs locking is very small, far smaller than the time
> spent sleeping inside writei() or wait().  How can just the critical
> section be protected without placing the locking inside alsa-lib?

Well, in general it's no good idea to use a blocking write for
multi-thread programs.  Most of codes I know use a direct poll() call
for a better control.  The blocking mode is basically for dumb program
that doesn't need a control.

Though, I see your point, too.  Of course it'd be better if there is
an atomic snd_pcm_delay() call.  I think it's possible to give a
consistent value without locking.  Here I meant a value that doesn't
express the exact position of the very current time, but at least a
position that is being processed.  It'll likely end up calling
snd_pcm_mmap_avail(), and this won't involve with the sync / update
procedure.

Well, just a thought, for now.


Takashi


So, the "dumb program" is the GStreamer ALSA Sink plugin.  What does an ALSA "poll" example look like?

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-13 19:41                 ` Trent Piepho
                                     ` (2 preceding siblings ...)
  2012-11-13 20:52                   ` Krakora Robert-B42341
@ 2012-11-14  8:02                   ` David Henningsson
  2012-11-14 12:55                     ` Krakora Robert-B42341
  2012-11-14 19:49                     ` Trent Piepho
  3 siblings, 2 replies; 32+ messages in thread
From: David Henningsson @ 2012-11-14  8:02 UTC (permalink / raw)
  To: Trent Piepho; +Cc: Takashi Iwai, alsa-devel, Krakora Robert-B42341

On 11/13/2012 08:41 PM, Trent Piepho wrote:
> On Tue, Nov 13, 2012 at 8:50 AM, Takashi Iwai <tiwai@suse.de> wrote:
>> At Tue, 13 Nov 2012 13:39:24 +0000,
>> Krakora Robert-B42341 wrote:
>>> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact other functionality within ALSA Lib.
>>
>> No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
>> stuff.
>>
>
> The problem with introduction serialization outside alsa-lib is that
> you must now serialize entire ALSA calls.  The locks must be held for
> far too long.
>
> Consider snd_pcm_writei(), most of the time is usually spent blocked
> waiting for a period to elapse.  It is perfectly ok to call
> snd_pcm_delay() during this time.  But if one isn't allowed to make
> any other pcm calls during snd_pcm_writei() then this can't be done.
>
> It's a pretty big problem.  Most code using blocking mode is going to
> write another period as soon as the writei call returns from the last
> write.  It will spend almost all its time inside snd_pcm_writei() and
> thus will always be holding the app's pcm stream lock.  As soon as it
> releases the lock it grabs it again for the next write.  Another
> thread trying to call snd_pcm_delay() will virtually NEVER get a
> chance.  Not only is it unnecessary stopped from getting the delay
> while another thread is blocked inside writei(), but it won't get a
> chance to call it between writei() calls either.
>
> But there doesn't need to be a conflict, since the actual critical
> section that needs locking is very small, far smaller than the time
> spent sleeping inside writei() or wait().  How can just the critical
> section be protected without placing the locking inside alsa-lib?

Hmm, but the great majority of programs are not interested in accessing 
alsa-lib from multiple threads in the way that's currently unsafe. That 
includes programs who are very dependent on low latency. I would not 
like to see all these programs to suffer from the overhead of adding 
locks here and there, even if those locks are small.

You claim that the Gstreamer ALSA sink plugin accesses alsa-lib from two 
threads simultaneously. Could you elaborate on how this can happen, 
maybe it is easy to fix?



-- 
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-14  8:02                   ` David Henningsson
@ 2012-11-14 12:55                     ` Krakora Robert-B42341
  2012-11-14 19:49                     ` Trent Piepho
  1 sibling, 0 replies; 32+ messages in thread
From: Krakora Robert-B42341 @ 2012-11-14 12:55 UTC (permalink / raw)
  To: David Henningsson, Trent Piepho; +Cc: Takashi Iwai, alsa-devel

From: alsa-devel-bounces@alsa-project.org [alsa-devel-bounces@alsa-project.org] on behalf of David Henningsson [david.henningsson@canonical.com]
Sent: Wednesday, November 14, 2012 3:02 AM
To: Trent Piepho
Cc: Takashi Iwai; alsa-devel@alsa-project.org; Krakora Robert-B42341
Subject: Re: [alsa-devel] Races in alsa-lib with threads

On 11/13/2012 08:41 PM, Trent Piepho wrote:
> On Tue, Nov 13, 2012 at 8:50 AM, Takashi Iwai <tiwai@suse.de> wrote:
>> At Tue, 13 Nov 2012 13:39:24 +0000,
>> Krakora Robert-B42341 wrote:
>>> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes that it is thread safe.  The fix crafted by one of Trent's colleagues (attached) seems to be the way to go.  However, I don't know how it would impact other functionality within ALSA Lib.
>>
>> No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
>> stuff.
>>
>
> The problem with introduction serialization outside alsa-lib is that
> you must now serialize entire ALSA calls.  The locks must be held for
> far too long.
>
> Consider snd_pcm_writei(), most of the time is usually spent blocked
> waiting for a period to elapse.  It is perfectly ok to call
> snd_pcm_delay() during this time.  But if one isn't allowed to make
> any other pcm calls during snd_pcm_writei() then this can't be done.
>
> It's a pretty big problem.  Most code using blocking mode is going to
> write another period as soon as the writei call returns from the last
> write.  It will spend almost all its time inside snd_pcm_writei() and
> thus will always be holding the app's pcm stream lock.  As soon as it
> releases the lock it grabs it again for the next write.  Another
> thread trying to call snd_pcm_delay() will virtually NEVER get a
> chance.  Not only is it unnecessary stopped from getting the delay
> while another thread is blocked inside writei(), but it won't get a
> chance to call it between writei() calls either.
>
> But there doesn't need to be a conflict, since the actual critical
> section that needs locking is very small, far smaller than the time
> spent sleeping inside writei() or wait().  How can just the critical
> section be protected without placing the locking inside alsa-lib?

Hmm, but the great majority of programs are not interested in accessing
alsa-lib from multiple threads in the way that's currently unsafe. That
includes programs who are very dependent on low latency. I would not
like to see all these programs to suffer from the overhead of adding
locks here and there, even if those locks are small.

You claim that the Gstreamer ALSA sink plugin accesses alsa-lib from two
threads simultaneously. Could you elaborate on how this can happen,
maybe it is easy to fix?



--
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

Hi David,

It is not just merely a claim, it is a fact that the GStreamer ALSA Sink plugin calls snd_pcm_delay() on a different thread from snd_pcm_writei().  We believe that we may now have a workable solution and Jarloslav updated the ALSA wiki to reflect that ALSA is SMP/thread safe in the kernel space but no in user space.  I believe that this is probably where the disconnect was; developers, that do not develop but merely use ALSA, misled by the original statement at the top of the ALSA wiki that ALSA was thread safe.  I think we all understand the issue of added latency in regards to the addition of mutexes and are in agreement with the ALSA developers in this regard.

Best Regards,

Rob Krakora

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-14  8:02                   ` David Henningsson
  2012-11-14 12:55                     ` Krakora Robert-B42341
@ 2012-11-14 19:49                     ` Trent Piepho
  2012-11-14 20:03                       ` Rémi Denis-Courmont
  2012-11-15  7:39                       ` Takashi Iwai
  1 sibling, 2 replies; 32+ messages in thread
From: Trent Piepho @ 2012-11-14 19:49 UTC (permalink / raw)
  To: David Henningsson; +Cc: Takashi Iwai, alsa-devel, Krakora Robert-B42341

On Wed, Nov 14, 2012 at 3:02 AM, David Henningsson
<david.henningsson@canonical.com> wrote:
> On 11/13/2012 08:41 PM, Trent Piepho wrote:
>>
>> On Tue, Nov 13, 2012 at 8:50 AM, Takashi Iwai <tiwai@suse.de> wrote:
>>>
>>> At Tue, 13 Nov 2012 13:39:24 +0000,
>>> Krakora Robert-B42341 wrote:
>>>>
>>>> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes
>>>> that it is thread safe.  The fix crafted by one of Trent's colleagues
>>>> (attached) seems to be the way to go.  However, I don't know how it would
>>>> impact other functionality within ALSA Lib.
>>>
>>>
>>> No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
>>> stuff.
>>>
>>
>> The problem with introduction serialization outside alsa-lib is that
>> you must now serialize entire ALSA calls.  The locks must be held for
>> far too long.
>>
>> Consider snd_pcm_writei(), most of the time is usually spent blocked
>> waiting for a period to elapse.  It is perfectly ok to call
>> snd_pcm_delay() during this time.  But if one isn't allowed to make
>> any other pcm calls during snd_pcm_writei() then this can't be done.
>>
>> It's a pretty big problem.  Most code using blocking mode is going to
>> write another period as soon as the writei call returns from the last
>> write.  It will spend almost all its time inside snd_pcm_writei() and
>> thus will always be holding the app's pcm stream lock.  As soon as it
>> releases the lock it grabs it again for the next write.  Another
>> thread trying to call snd_pcm_delay() will virtually NEVER get a
>> chance.  Not only is it unnecessary stopped from getting the delay
>> while another thread is blocked inside writei(), but it won't get a
>> chance to call it between writei() calls either.
>>
>> But there doesn't need to be a conflict, since the actual critical
>> section that needs locking is very small, far smaller than the time
>> spent sleeping inside writei() or wait().  How can just the critical
>> section be protected without placing the locking inside alsa-lib?
>
> Hmm, but the great majority of programs are not interested in accessing
> alsa-lib from multiple threads in the way that's currently unsafe. That
> includes programs who are very dependent on low latency. I would not like to
> see all these programs to suffer from the overhead of adding locks here and
> there, even if those locks are small.

Maybe they just don't know it's unsafe and don't hit a race often
enough to notice?

> You claim that the Gstreamer ALSA sink plugin accesses alsa-lib from two
> threads simultaneously. Could you elaborate on how this can happen, maybe it
> is easy to fix?

gstreamer has no lock around the call to snd_pcm_delay().  So it can
race with snd_pcm_wait() or snd_pcm_writei(), which are called in
another thread.  There is a lock around the block of code calling
wait()/writei(), but this lock isn't used for calling delay().  It
seems that they didn't know there would be a problem.

And if you're not using the alsa rate plugin, then I don't think
snd_pcm_delay() has a race with snd_pcm_writei().  delay for a hw
device will call an ioctl to just get the delay.  I think that's ok,
assuming the kernel part has no races.  It's only when using the rate
plugin that snd_pcm_delay() will try to update the pointer and race
with writei.

So unless you use the rate plugin, you'll never notice this race.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-14 19:49                     ` Trent Piepho
@ 2012-11-14 20:03                       ` Rémi Denis-Courmont
  2012-11-14 20:06                         ` Krakora Robert-B42341
  2012-11-14 20:54                         ` Trent Piepho
  2012-11-15  7:39                       ` Takashi Iwai
  1 sibling, 2 replies; 32+ messages in thread
From: Rémi Denis-Courmont @ 2012-11-14 20:03 UTC (permalink / raw)
  To: alsa-devel; +Cc: Trent Piepho

	Hello,

Le mercredi 14 novembre 2012 21:49:36, Trent Piepho a écrit :
> > You claim that the Gstreamer ALSA sink plugin accesses alsa-lib from two
> > threads simultaneously. Could you elaborate on how this can happen, maybe
> > it is easy to fix?
> 
> gstreamer has no lock around the call to snd_pcm_delay().  So it can
> race with snd_pcm_wait() or snd_pcm_writei(), which are called in
> another thread.  There is a lock around the block of code calling
> wait()/writei(), but this lock isn't used for calling delay().

Use non-blocking I/O and poll(). Then the snd_pcm_write() calls will not sleep 
and can be interlocked with snd_pcm_delay() calls.

> It seems that they didn't know there would be a problem.

Eh? It is rather the exception for a library to be thread-safe when using the 
same object in multiple threads.

It looks more like "they" did not pay attention to what they were doing.

-- 
Rémi Denis-Courmont
http://www.remlab.net/

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-14 20:03                       ` Rémi Denis-Courmont
@ 2012-11-14 20:06                         ` Krakora Robert-B42341
  2012-11-14 20:54                         ` Trent Piepho
  1 sibling, 0 replies; 32+ messages in thread
From: Krakora Robert-B42341 @ 2012-11-14 20:06 UTC (permalink / raw)
  To: Rémi Denis-Courmont, alsa-devel; +Cc: Trent Piepho

________________________________________
From: alsa-devel-bounces@alsa-project.org [alsa-devel-bounces@alsa-project.org] on behalf of Rémi Denis-Courmont [remi@remlab.net]
Sent: Wednesday, November 14, 2012 3:03 PM
To: alsa-devel@alsa-project.org
Cc: Trent Piepho
Subject: Re: [alsa-devel] Races in alsa-lib with threads

        Hello,

Le mercredi 14 novembre 2012 21:49:36, Trent Piepho a écrit :
> > You claim that the Gstreamer ALSA sink plugin accesses alsa-lib from two
> > threads simultaneously. Could you elaborate on how this can happen, maybe
> > it is easy to fix?
>
> gstreamer has no lock around the call to snd_pcm_delay().  So it can
> race with snd_pcm_wait() or snd_pcm_writei(), which are called in
> another thread.  There is a lock around the block of code calling
> wait()/writei(), but this lock isn't used for calling delay().

Use non-blocking I/O and poll(). Then the snd_pcm_write() calls will not sleep
and can be interlocked with snd_pcm_delay() calls.

> It seems that they didn't know there would be a problem.

Eh? It is rather the exception for a library to be thread-safe when using the
same object in multiple threads.

It looks more like "they" did not pay attention to what they were doing.

--
Rémi Denis-Courmont
http://www.remlab.net/
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

HI Rémi,

We are using non-blocking mode with snd_pcm_wait() and snd_pcm_writei().  We have a workable solution.  Thanks for the advice.

Best Regards.

Rob

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-14 20:03                       ` Rémi Denis-Courmont
  2012-11-14 20:06                         ` Krakora Robert-B42341
@ 2012-11-14 20:54                         ` Trent Piepho
  2012-11-14 21:19                           ` Rémi Denis-Courmont
  1 sibling, 1 reply; 32+ messages in thread
From: Trent Piepho @ 2012-11-14 20:54 UTC (permalink / raw)
  To: Rémi Denis-Courmont; +Cc: alsa-devel

On Wed, Nov 14, 2012 at 3:03 PM, Rémi Denis-Courmont <remi@remlab.net> wrote:
> Le mercredi 14 novembre 2012 21:49:36, Trent Piepho a écrit :
>> > You claim that the Gstreamer ALSA sink plugin accesses alsa-lib from two
>> > threads simultaneously. Could you elaborate on how this can happen, maybe
>> > it is easy to fix?
>>
>> gstreamer has no lock around the call to snd_pcm_delay().  So it can
>> race with snd_pcm_wait() or snd_pcm_writei(), which are called in
>> another thread.  There is a lock around the block of code calling
>> wait()/writei(), but this lock isn't used for calling delay().
>
> Use non-blocking I/O and poll(). Then the snd_pcm_write() calls will not sleep
> and can be interlocked with snd_pcm_delay() calls.

gstreamer uses non-blocking I/O.  But uses snd_pcm_wait rather than
poll directly.  I wonder if poll() is entirely correct when ALSA
plugins are in the chain?

"the snd_pcm_write() calls ...can be interlocked with snd_pcm_delay() calls".

It's still a race to call writei() and delay() at the same time, even
if writei() is non-blocking.  But only if the rate plugin is being
used.  Of course the actual race is very small, and doesn't include
the time spent doing resampling or mixing in plugins which are still
part of the writei() call in non-blocking mode.  It's basically like
the BKL around every ALSA call.

>> It seems that they didn't know there would be a problem.
>
> Eh? It is rather the exception for a library to be thread-safe when using the
> same object in multiple threads.

It's ok to call kernel syscalls on the same fd at the same time.  The
kernel used to have the BKL for this.  Now it has fine grained locking
around the actual critical sections.  So if ALSA is called thread
safe, it doesn't seem that unreasonable to think one can do this.

> It looks more like "they" did not pay attention to what they were doing.

I think the point is that this bug was in gstreamer.  gstreamer is
commonly used by many people.  The bug has been there for years.  Many
programmers have looked at the code.  Yet no one noticed it or tracked
it down until now.  If it's so obvious why did it take so long?

You aren't aware of this problem in other multi-threaded code, but
that doesn't mean it doesn't exist.  You weren't aware of the problem
in gstreamer and yet it exists.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-14 20:54                         ` Trent Piepho
@ 2012-11-14 21:19                           ` Rémi Denis-Courmont
  2012-11-15  1:52                             ` Krakora Robert-B42341
  0 siblings, 1 reply; 32+ messages in thread
From: Rémi Denis-Courmont @ 2012-11-14 21:19 UTC (permalink / raw)
  To: Trent Piepho; +Cc: alsa-devel

Le mercredi 14 novembre 2012 22:54:15, Trent Piepho a écrit :
> gstreamer uses non-blocking I/O.  But uses snd_pcm_wait rather than
> poll directly.  I wonder if poll() is entirely correct when ALSA
> plugins are in the chain?
> 
> "the snd_pcm_write() calls ...can be interlocked with snd_pcm_delay()
> calls".
> 
> It's still a race to call writei() and delay() at the same time, even
> if writei() is non-blocking.  But only if the rate plugin is being
> used.  Of course the actual race is very small, and doesn't include
> the time spent doing resampling or mixing in plugins which are still
> part of the writei() call in non-blocking mode.  It's basically like
> the BKL around every ALSA call.

Of course, you will need a lock around many ALSA calls, at least all 
potentially concurrent call. But that's a great improvement over holding a 
lock while sleeping inside a blocking I/O operation.

> >> It seems that they didn't know there would be a problem.
> > 
> > Eh? It is rather the exception for a library to be thread-safe when using
> > the same object in multiple threads.
> 
> It's ok to call kernel syscalls on the same fd at the same time.

Yes and no. Typically the kernel protects itself against undefined behaviour 
induced by user space. But it does not protect user space against their own 
undefined behaviour. The file descriptors table is a very good example of that.

In fact,  calling snd_pcm_delay() and snd_pcm_write() concurrently is just 
PLAIN STUPID. The delay measurement may or may not include the impeding write 
operation, or maybe only a part of it. Essentially, the delay value is not 
much more than random garbage.

Hiding a mutex inside alsa-lib will NOT fix this intrinsic problem: Instead of 
having data races in memory, you will have logical races and gstreamer would 
still be buggy in some ways.

> The kernel used to have the BKL for this.  Now it has fine grained locking
> around the actual critical sections.  So if ALSA is called thread
> safe, it doesn't seem that unreasonable to think one can do this.

Thread-safe means you can enter the library functions from multiple threads. 
Thread-safe never meant that you can enter the library functions from multiple 
threads with the SAME DATA.

See also Lennart's and Kay's example library...

> > It looks more like "they" did not pay attention to what they were doing.
> 
> I think the point is that this bug was in gstreamer.  gstreamer is
> commonly used by many people.  The bug has been there for years.  Many
> programmers have looked at the code.  Yet no one noticed it or tracked
> it down until now.  If it's so obvious why did it take so long?
> 
> You aren't aware of this problem in other multi-threaded code, but
> that doesn't mean it doesn't exist.  You weren't aware of the problem
> in gstreamer and yet it exists.

Hey, I don't use gstreamer.  VLC has interlocked its ALSA calls for many years 
and I did not blame alsa-lib for not doing it internally. In fact, I realized 
that this was not a problem that ALSA could nor should solve.

Also, all audio APIs are like that. Even PulseAudio requires the application 
to acquire locks explicitly.

-- 
Rémi Denis-Courmont
http://www.remlab.net/

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-14 21:19                           ` Rémi Denis-Courmont
@ 2012-11-15  1:52                             ` Krakora Robert-B42341
  0 siblings, 0 replies; 32+ messages in thread
From: Krakora Robert-B42341 @ 2012-11-15  1:52 UTC (permalink / raw)
  To: Rémi Denis-Courmont, Trent Piepho; +Cc: alsa-devel

From: alsa-devel-bounces@alsa-project.org [alsa-devel-bounces@alsa-project.org] on behalf of Rémi Denis-Courmont [remi@remlab.net]
Sent: Wednesday, November 14, 2012 4:19 PM
To: Trent Piepho
Cc: alsa-devel@alsa-project.org
Subject: Re: [alsa-devel] Races in alsa-lib with threads

Le mercredi 14 novembre 2012 22:54:15, Trent Piepho a écrit :
> gstreamer uses non-blocking I/O.  But uses snd_pcm_wait rather than
> poll directly.  I wonder if poll() is entirely correct when ALSA
> plugins are in the chain?
>
> "the snd_pcm_write() calls ...can be interlocked with snd_pcm_delay()
> calls".
>
> It's still a race to call writei() and delay() at the same time, even
> if writei() is non-blocking.  But only if the rate plugin is being
> used.  Of course the actual race is very small, and doesn't include
> the time spent doing resampling or mixing in plugins which are still
> part of the writei() call in non-blocking mode.  It's basically like
> the BKL around every ALSA call.

Of course, you will need a lock around many ALSA calls, at least all
potentially concurrent call. But that's a great improvement over holding a
lock while sleeping inside a blocking I/O operation.

> >> It seems that they didn't know there would be a problem.
> >
> > Eh? It is rather the exception for a library to be thread-safe when using
> > the same object in multiple threads.
>
> It's ok to call kernel syscalls on the same fd at the same time.

Yes and no. Typically the kernel protects itself against undefined behaviour
induced by user space. But it does not protect user space against their own
undefined behaviour. The file descriptors table is a very good example of that.

In fact,  calling snd_pcm_delay() and snd_pcm_write() concurrently is just
PLAIN STUPID. The delay measurement may or may not include the impeding write
operation, or maybe only a part of it. Essentially, the delay value is not
much more than random garbage.

Hiding a mutex inside alsa-lib will NOT fix this intrinsic problem: Instead of
having data races in memory, you will have logical races and gstreamer would
still be buggy in some ways.

> The kernel used to have the BKL for this.  Now it has fine grained locking
> around the actual critical sections.  So if ALSA is called thread
> safe, it doesn't seem that unreasonable to think one can do this.

Thread-safe means you can enter the library functions from multiple threads.
Thread-safe never meant that you can enter the library functions from multiple
threads with the SAME DATA.

See also Lennart's and Kay's example library...

> > It looks more like "they" did not pay attention to what they were doing.
>
> I think the point is that this bug was in gstreamer.  gstreamer is
> commonly used by many people.  The bug has been there for years.  Many
> programmers have looked at the code.  Yet no one noticed it or tracked
> it down until now.  If it's so obvious why did it take so long?
>
> You aren't aware of this problem in other multi-threaded code, but
> that doesn't mean it doesn't exist.  You weren't aware of the problem
> in gstreamer and yet it exists.

Hey, I don't use gstreamer.  VLC has interlocked its ALSA calls for many years
and I did not blame alsa-lib for not doing it internally. In fact, I realized
that this was not a problem that ALSA could nor should solve.

Also, all audio APIs are like that. Even PulseAudio requires the application
to acquire locks explicitly.

--
Rémi Denis-Courmont
http://www.remlab.net/
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

Hi Remi,

We have a solution now that we are testing where the ALSA calls reside is a single thread within the GStreamer ALSA Sink plugin.  Once we tested it for a bit, we will submit it to the GStreamer folks for approval.  Now that the ALSA Wiki has been updated with Jarloslav's caveat about ALSA thread safety, newbies should no longer misuse that ALSA Lib API.  Thanks so much for your insight and for Takashi's and Jarloslav's help as well.  Sorry to take up so much of your time.  ;-)

Best Regards,

Rob

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-14 19:49                     ` Trent Piepho
  2012-11-14 20:03                       ` Rémi Denis-Courmont
@ 2012-11-15  7:39                       ` Takashi Iwai
  2012-11-15 13:05                         ` Krakora Robert-B42341
  1 sibling, 1 reply; 32+ messages in thread
From: Takashi Iwai @ 2012-11-15  7:39 UTC (permalink / raw)
  To: Trent Piepho; +Cc: alsa-devel, David Henningsson, Krakora Robert-B42341

At Wed, 14 Nov 2012 14:49:36 -0500,
Trent Piepho wrote:
> 
> On Wed, Nov 14, 2012 at 3:02 AM, David Henningsson
> <david.henningsson@canonical.com> wrote:
> > On 11/13/2012 08:41 PM, Trent Piepho wrote:
> >>
> >> On Tue, Nov 13, 2012 at 8:50 AM, Takashi Iwai <tiwai@suse.de> wrote:
> >>>
> >>> At Tue, 13 Nov 2012 13:39:24 +0000,
> >>> Krakora Robert-B42341 wrote:
> >>>>
> >>>> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes
> >>>> that it is thread safe.  The fix crafted by one of Trent's colleagues
> >>>> (attached) seems to be the way to go.  However, I don't know how it would
> >>>> impact other functionality within ALSA Lib.
> >>>
> >>>
> >>> No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
> >>> stuff.
> >>>
> >>
> >> The problem with introduction serialization outside alsa-lib is that
> >> you must now serialize entire ALSA calls.  The locks must be held for
> >> far too long.
> >>
> >> Consider snd_pcm_writei(), most of the time is usually spent blocked
> >> waiting for a period to elapse.  It is perfectly ok to call
> >> snd_pcm_delay() during this time.  But if one isn't allowed to make
> >> any other pcm calls during snd_pcm_writei() then this can't be done.
> >>
> >> It's a pretty big problem.  Most code using blocking mode is going to
> >> write another period as soon as the writei call returns from the last
> >> write.  It will spend almost all its time inside snd_pcm_writei() and
> >> thus will always be holding the app's pcm stream lock.  As soon as it
> >> releases the lock it grabs it again for the next write.  Another
> >> thread trying to call snd_pcm_delay() will virtually NEVER get a
> >> chance.  Not only is it unnecessary stopped from getting the delay
> >> while another thread is blocked inside writei(), but it won't get a
> >> chance to call it between writei() calls either.
> >>
> >> But there doesn't need to be a conflict, since the actual critical
> >> section that needs locking is very small, far smaller than the time
> >> spent sleeping inside writei() or wait().  How can just the critical
> >> section be protected without placing the locking inside alsa-lib?
> >
> > Hmm, but the great majority of programs are not interested in accessing
> > alsa-lib from multiple threads in the way that's currently unsafe. That
> > includes programs who are very dependent on low latency. I would not like to
> > see all these programs to suffer from the overhead of adding locks here and
> > there, even if those locks are small.
> 
> Maybe they just don't know it's unsafe and don't hit a race often
> enough to notice?

Maybe, but many multi-threaded codes are carefully holding locks
already in the caller side.

> > You claim that the Gstreamer ALSA sink plugin accesses alsa-lib from two
> > threads simultaneously. Could you elaborate on how this can happen, maybe it
> > is easy to fix?
> 
> gstreamer has no lock around the call to snd_pcm_delay().  So it can
> race with snd_pcm_wait() or snd_pcm_writei(), which are called in
> another thread.  There is a lock around the block of code calling
> wait()/writei(), but this lock isn't used for calling delay().  It
> seems that they didn't know there would be a problem.

Actually the atomic lock things found in alsa-lib code is no proper
lock for avoiding this kind of race.  It's equivalent with seq_lock()
in kernel, and it's used to make snd_pcm_status() consistent.  It
doesn't protect against the data corruption due to concurrent
accesses.

A part of concurrent access problems in the rate plugin can be fixed
by a patch like below.  In essence, it avoids updating the internal
hw_ptr value but just calculates the current hw_ptr and returns.  Most
of other changes in pcm_local.h are only refactoring. But this is
obviously just a bandaid on the spot, it doesn't solve the whole
problems at all.  So I don't buy this.

One modest solution would be to add a bit flag SND_PCM_THREAD_SAFE to
snd_pcm_open(), and activate pthread mutex locks conditionally only
with this bit set.  This isn't designed for any performance-wise
codes, and it's just for protecting concurrent accesses, so should be
called like SND_PCM_THREAD_SAFE_FOR_DUMMIES...


Takashi

---
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
index 8cf7c3d..af4695b 100644
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -420,10 +420,15 @@ static inline int snd_pcm_check_error(snd_pcm_t *pcm, int err)
 	return err;
 }
 
-static inline snd_pcm_uframes_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm)
+static inline snd_pcm_uframes_t
+_snd_pcm_calc_avail(snd_pcm_t *pcm, snd_pcm_uframes_t hw_ptr,
+		    snd_pcm_uframes_t appl_ptr)
 {
 	snd_pcm_sframes_t avail;
-	avail = *pcm->hw.ptr + pcm->buffer_size - *pcm->appl.ptr;
+
+	avail = hw_ptr - appl_ptr;
+	if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
+		avail += pcm->buffer_size;
 	if (avail < 0)
 		avail += pcm->boundary;
 	else if ((snd_pcm_uframes_t) avail >= pcm->boundary)
@@ -431,44 +436,22 @@ static inline snd_pcm_uframes_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm)
 	return avail;
 }
 
-static inline snd_pcm_uframes_t snd_pcm_mmap_capture_avail(snd_pcm_t *pcm)
-{
-	snd_pcm_sframes_t avail;
-	avail = *pcm->hw.ptr - *pcm->appl.ptr;
-	if (avail < 0)
-		avail += pcm->boundary;
-	return avail;
-}
-
 static inline snd_pcm_uframes_t snd_pcm_mmap_avail(snd_pcm_t *pcm)
 {
-	if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
-		return snd_pcm_mmap_playback_avail(pcm);
-	else
-		return snd_pcm_mmap_capture_avail(pcm);
+	return _snd_pcm_calc_avail(pcm, *pcm->hw.ptr, *pcm->appl.ptr);
 }
 
-static inline snd_pcm_sframes_t snd_pcm_mmap_playback_hw_avail(snd_pcm_t *pcm)
-{
-	return pcm->buffer_size - snd_pcm_mmap_playback_avail(pcm);
-}
-
-static inline snd_pcm_sframes_t snd_pcm_mmap_capture_hw_avail(snd_pcm_t *pcm)
-{
-	return pcm->buffer_size - snd_pcm_mmap_capture_avail(pcm);
-}
+#define snd_pcm_mmap_playback_avail	snd_pcm_mmap_avail
+#define snd_pcm_mmap_capture_avail	snd_pcm_mmap_avail
 
 static inline snd_pcm_sframes_t snd_pcm_mmap_hw_avail(snd_pcm_t *pcm)
 {
-	snd_pcm_sframes_t avail;
-	avail = *pcm->hw.ptr - *pcm->appl.ptr;
-	if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
-		avail += pcm->buffer_size;
-	if (avail < 0)
-		avail += pcm->boundary;
-	return pcm->buffer_size - avail;
+	return pcm->buffer_size - snd_pcm_mmap_avail(pcm);
 }
 
+#define snd_pcm_mmap_playback_hw_avail	snd_pcm_mmap_hw_avail
+#define snd_pcm_mmap_capture_hw_avail	snd_pcm_mmap_hw_avail
+
 static inline const snd_pcm_channel_area_t *snd_pcm_mmap_areas(snd_pcm_t *pcm)
 {
 	if (pcm->stopped_areas &&
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index 54a3e67..340a4d3 100644
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -613,21 +613,28 @@ static inline snd_pcm_sframes_t snd_pcm_rate_move_applptr(snd_pcm_t *pcm, snd_pc
 	return diff;
 }
 
-static inline void snd_pcm_rate_sync_hwptr(snd_pcm_t *pcm)
+static inline snd_pcm_uframes_t snd_pcm_rate_get_hwptr(snd_pcm_t *pcm)
 {
 	snd_pcm_rate_t *rate = pcm->private_data;
 	snd_pcm_uframes_t slave_hw_ptr = *rate->gen.slave->hw.ptr;
 
 	if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
-		return;
+		return rate->hw_ptr;
 	/* FIXME: boundary overlap of slave hw_ptr isn't evaluated here!
 	 *        e.g. if slave rate is small... 
 	 */
-	rate->hw_ptr =
-		(slave_hw_ptr / rate->gen.slave->period_size) * pcm->period_size +
+	return (slave_hw_ptr / rate->gen.slave->period_size) * pcm->period_size +
 		rate->ops.input_frames(rate->obj, slave_hw_ptr % rate->gen.slave->period_size);
 }
 
+static inline void snd_pcm_rate_sync_hwptr(snd_pcm_t *pcm)
+{
+	snd_pcm_rate_t *rate = pcm->private_data;
+
+	if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
+		rate->hw_ptr = snd_pcm_rate_get_hwptr(pcm);
+}
+
 static int snd_pcm_rate_hwsync(snd_pcm_t *pcm)
 {
 	snd_pcm_rate_t *rate = pcm->private_data;
@@ -642,11 +649,11 @@ static int snd_pcm_rate_hwsync(snd_pcm_t *pcm)
 
 static int snd_pcm_rate_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
-	snd_pcm_rate_hwsync(pcm);
-	if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
-		*delayp = snd_pcm_mmap_playback_hw_avail(pcm);
-	else
-		*delayp = snd_pcm_mmap_capture_hw_avail(pcm);
+	snd_pcm_rate_t *rate = pcm->private_data;
+
+	snd_pcm_hwsync(rate->gen.slave);
+	*delayp = _snd_pcm_calc_avail(pcm, snd_pcm_rate_get_hwptr(pcm),
+				      *pcm->appl.ptr);
 	return 0;
 }
 

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: Races in alsa-lib with threads
  2012-11-15  7:39                       ` Takashi Iwai
@ 2012-11-15 13:05                         ` Krakora Robert-B42341
  0 siblings, 0 replies; 32+ messages in thread
From: Krakora Robert-B42341 @ 2012-11-15 13:05 UTC (permalink / raw)
  To: Takashi Iwai, Trent Piepho; +Cc: alsa-devel, David Henningsson

From: Takashi Iwai [tiwai@suse.de]
Sent: Thursday, November 15, 2012 2:39 AM
To: Trent Piepho
Cc: David Henningsson; alsa-devel@alsa-project.org; Krakora Robert-B42341
Subject: Re: [alsa-devel] Races in alsa-lib with threads

At Wed, 14 Nov 2012 14:49:36 -0500,
Trent Piepho wrote:
>
> On Wed, Nov 14, 2012 at 3:02 AM, David Henningsson
> <david.henningsson@canonical.com> wrote:
> > On 11/13/2012 08:41 PM, Trent Piepho wrote:
> >>
> >> On Tue, Nov 13, 2012 at 8:50 AM, Takashi Iwai <tiwai@suse.de> wrote:
> >>>
> >>> At Tue, 13 Nov 2012 13:39:24 +0000,
> >>> Krakora Robert-B42341 wrote:
> >>>>
> >>>> The way that the GStreamer ALSA Sink Plugin is using ALSA Lib assumes
> >>>> that it is thread safe.  The fix crafted by one of Trent's colleagues
> >>>> (attached) seems to be the way to go.  However, I don't know how it would
> >>>> impact other functionality within ALSA Lib.
> >>>
> >>>
> >>> No, sorry, we don't want to introduce pthread_lock in alsa-lib PCM
> >>> stuff.
> >>>
> >>
> >> The problem with introduction serialization outside alsa-lib is that
> >> you must now serialize entire ALSA calls.  The locks must be held for
> >> far too long.
> >>
> >> Consider snd_pcm_writei(), most of the time is usually spent blocked
> >> waiting for a period to elapse.  It is perfectly ok to call
> >> snd_pcm_delay() during this time.  But if one isn't allowed to make
> >> any other pcm calls during snd_pcm_writei() then this can't be done.
> >>
> >> It's a pretty big problem.  Most code using blocking mode is going to
> >> write another period as soon as the writei call returns from the last
> >> write.  It will spend almost all its time inside snd_pcm_writei() and
> >> thus will always be holding the app's pcm stream lock.  As soon as it
> >> releases the lock it grabs it again for the next write.  Another
> >> thread trying to call snd_pcm_delay() will virtually NEVER get a
> >> chance.  Not only is it unnecessary stopped from getting the delay
> >> while another thread is blocked inside writei(), but it won't get a
> >> chance to call it between writei() calls either.
> >>
> >> But there doesn't need to be a conflict, since the actual critical
> >> section that needs locking is very small, far smaller than the time
> >> spent sleeping inside writei() or wait().  How can just the critical
> >> section be protected without placing the locking inside alsa-lib?
> >
> > Hmm, but the great majority of programs are not interested in accessing
> > alsa-lib from multiple threads in the way that's currently unsafe. That
> > includes programs who are very dependent on low latency. I would not like to
> > see all these programs to suffer from the overhead of adding locks here and
> > there, even if those locks are small.
>
> Maybe they just don't know it's unsafe and don't hit a race often
> enough to notice?

Maybe, but many multi-threaded codes are carefully holding locks
already in the caller side.

> > You claim that the Gstreamer ALSA sink plugin accesses alsa-lib from two
> > threads simultaneously. Could you elaborate on how this can happen, maybe it
> > is easy to fix?
>
> gstreamer has no lock around the call to snd_pcm_delay().  So it can
> race with snd_pcm_wait() or snd_pcm_writei(), which are called in
> another thread.  There is a lock around the block of code calling
> wait()/writei(), but this lock isn't used for calling delay().  It
> seems that they didn't know there would be a problem.

Actually the atomic lock things found in alsa-lib code is no proper
lock for avoiding this kind of race.  It's equivalent with seq_lock()
in kernel, and it's used to make snd_pcm_status() consistent.  It
doesn't protect against the data corruption due to concurrent
accesses.

A part of concurrent access problems in the rate plugin can be fixed
by a patch like below.  In essence, it avoids updating the internal
hw_ptr value but just calculates the current hw_ptr and returns.  Most
of other changes in pcm_local.h are only refactoring. But this is
obviously just a bandaid on the spot, it doesn't solve the whole
problems at all.  So I don't buy this.

One modest solution would be to add a bit flag SND_PCM_THREAD_SAFE to
snd_pcm_open(), and activate pthread mutex locks conditionally only
with this bit set.  This isn't designed for any performance-wise
codes, and it's just for protecting concurrent accesses, so should be
called like SND_PCM_THREAD_SAFE_FOR_DUMMIES...


Takashi

---
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
index 8cf7c3d..af4695b 100644
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -420,10 +420,15 @@ static inline int snd_pcm_check_error(snd_pcm_t *pcm, int err)
        return err;
 }

-static inline snd_pcm_uframes_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm)
+static inline snd_pcm_uframes_t
+_snd_pcm_calc_avail(snd_pcm_t *pcm, snd_pcm_uframes_t hw_ptr,
+                   snd_pcm_uframes_t appl_ptr)
 {
        snd_pcm_sframes_t avail;
-       avail = *pcm->hw.ptr + pcm->buffer_size - *pcm->appl.ptr;
+
+       avail = hw_ptr - appl_ptr;
+       if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
+               avail += pcm->buffer_size;
        if (avail < 0)
                avail += pcm->boundary;
        else if ((snd_pcm_uframes_t) avail >= pcm->boundary)
@@ -431,44 +436,22 @@ static inline snd_pcm_uframes_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm)
        return avail;
 }

-static inline snd_pcm_uframes_t snd_pcm_mmap_capture_avail(snd_pcm_t *pcm)
-{
-       snd_pcm_sframes_t avail;
-       avail = *pcm->hw.ptr - *pcm->appl.ptr;
-       if (avail < 0)
-               avail += pcm->boundary;
-       return avail;
-}
-
 static inline snd_pcm_uframes_t snd_pcm_mmap_avail(snd_pcm_t *pcm)
 {
-       if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
-               return snd_pcm_mmap_playback_avail(pcm);
-       else
-               return snd_pcm_mmap_capture_avail(pcm);
+       return _snd_pcm_calc_avail(pcm, *pcm->hw.ptr, *pcm->appl.ptr);
 }

-static inline snd_pcm_sframes_t snd_pcm_mmap_playback_hw_avail(snd_pcm_t *pcm)
-{
-       return pcm->buffer_size - snd_pcm_mmap_playback_avail(pcm);
-}
-
-static inline snd_pcm_sframes_t snd_pcm_mmap_capture_hw_avail(snd_pcm_t *pcm)
-{
-       return pcm->buffer_size - snd_pcm_mmap_capture_avail(pcm);
-}
+#define snd_pcm_mmap_playback_avail    snd_pcm_mmap_avail
+#define snd_pcm_mmap_capture_avail     snd_pcm_mmap_avail

 static inline snd_pcm_sframes_t snd_pcm_mmap_hw_avail(snd_pcm_t *pcm)
 {
-       snd_pcm_sframes_t avail;
-       avail = *pcm->hw.ptr - *pcm->appl.ptr;
-       if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
-               avail += pcm->buffer_size;
-       if (avail < 0)
-               avail += pcm->boundary;
-       return pcm->buffer_size - avail;
+       return pcm->buffer_size - snd_pcm_mmap_avail(pcm);
 }

+#define snd_pcm_mmap_playback_hw_avail snd_pcm_mmap_hw_avail
+#define snd_pcm_mmap_capture_hw_avail  snd_pcm_mmap_hw_avail
+
 static inline const snd_pcm_channel_area_t *snd_pcm_mmap_areas(snd_pcm_t *pcm)
 {
        if (pcm->stopped_areas &&
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index 54a3e67..340a4d3 100644
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -613,21 +613,28 @@ static inline snd_pcm_sframes_t snd_pcm_rate_move_applptr(snd_pcm_t *pcm, snd_pc
        return diff;
 }

-static inline void snd_pcm_rate_sync_hwptr(snd_pcm_t *pcm)
+static inline snd_pcm_uframes_t snd_pcm_rate_get_hwptr(snd_pcm_t *pcm)
 {
        snd_pcm_rate_t *rate = pcm->private_data;
        snd_pcm_uframes_t slave_hw_ptr = *rate->gen.slave->hw.ptr;

        if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
-               return;
+               return rate->hw_ptr;
        /* FIXME: boundary overlap of slave hw_ptr isn't evaluated here!
         *        e.g. if slave rate is small...
         */
-       rate->hw_ptr =
-               (slave_hw_ptr / rate->gen.slave->period_size) * pcm->period_size +
+       return (slave_hw_ptr / rate->gen.slave->period_size) * pcm->period_size +
                rate->ops.input_frames(rate->obj, slave_hw_ptr % rate->gen.slave->period_size);
 }

+static inline void snd_pcm_rate_sync_hwptr(snd_pcm_t *pcm)
+{
+       snd_pcm_rate_t *rate = pcm->private_data;
+
+       if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
+               rate->hw_ptr = snd_pcm_rate_get_hwptr(pcm);
+}
+
 static int snd_pcm_rate_hwsync(snd_pcm_t *pcm)
 {
        snd_pcm_rate_t *rate = pcm->private_data;
@@ -642,11 +649,11 @@ static int snd_pcm_rate_hwsync(snd_pcm_t *pcm)

 static int snd_pcm_rate_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
-       snd_pcm_rate_hwsync(pcm);
-       if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
-               *delayp = snd_pcm_mmap_playback_hw_avail(pcm);
-       else
-               *delayp = snd_pcm_mmap_capture_hw_avail(pcm);
+       snd_pcm_rate_t *rate = pcm->private_data;
+
+       snd_pcm_hwsync(rate->gen.slave);
+       *delayp = _snd_pcm_calc_avail(pcm, snd_pcm_rate_get_hwptr(pcm),
+                                     *pcm->appl.ptr);
        return 0;
 }

Hi Takashi,

I believe that we have a workable solution that does not break the paradigm established by ALSA conforming to calls made exclusively in a single thread or in multiple threads with the using application providing locking (less efficient).  There is a disconnect here with developers using ALSA in their applications and not fully understanding the paradigm or the ramifications of using it incorrectly in a multithreaded environment.  I have seen old threads (no pun intended) where thread safety and ALSA has come up before and I am sorry for bringing it up yet again.  I believe that Jarloslav's added caveat to the Wiki should help.  As always, thanks for your quick and detail analysis.

Best Regards,

Rob Krakora

^ permalink raw reply related	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2012-11-15 13:05 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-10  2:03 Races in alsa-lib with threads Trent Piepho
2012-11-10 13:53 ` Takashi Iwai
2012-11-11 16:35   ` Jaroslav Kysela
2012-11-12 19:40     ` Rob Krakora
2012-11-13  6:32       ` Takashi Iwai
2012-11-13  7:14         ` Trent Piepho
2012-11-13  7:30           ` Takashi Iwai
     [not found]             ` <5175C6FEA820754B902FF6873E9285B00C985240@039-SN2MPN1-021.039d.mgd.msft.net>
2012-11-13 13:47               ` Krakora Robert-B42341
2012-11-13 13:50               ` Takashi Iwai
2012-11-13 14:04                 ` Krakora Robert-B42341
2012-11-13 14:18                   ` Takashi Iwai
2012-11-13 14:08                 ` Jaroslav Kysela
2012-11-13 14:15                   ` Krakora Robert-B42341
2012-11-13 14:19                   ` Takashi Iwai
2012-11-13 14:26                 ` Krakora Robert-B42341
2012-11-13 19:41                 ` Trent Piepho
2012-11-13 20:23                   ` Clemens Ladisch
2012-11-13 20:36                     ` Trent Piepho
2012-11-13 20:29                   ` Takashi Iwai
2012-11-13 20:55                     ` Krakora Robert-B42341
2012-11-13 21:11                       ` Krakora Robert-B42341
2012-11-13 20:52                   ` Krakora Robert-B42341
2012-11-14  8:02                   ` David Henningsson
2012-11-14 12:55                     ` Krakora Robert-B42341
2012-11-14 19:49                     ` Trent Piepho
2012-11-14 20:03                       ` Rémi Denis-Courmont
2012-11-14 20:06                         ` Krakora Robert-B42341
2012-11-14 20:54                         ` Trent Piepho
2012-11-14 21:19                           ` Rémi Denis-Courmont
2012-11-15  1:52                             ` Krakora Robert-B42341
2012-11-15  7:39                       ` Takashi Iwai
2012-11-15 13:05                         ` Krakora Robert-B42341

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.