[pulseaudio-discuss] [PATCH] alsa: Check respect return value of snd_pcm_mmap_commit()

David Henningsson david.henningsson at canonical.com
Wed Nov 12 06:48:00 PST 2014



On 2014-11-12 14:31, Peter Meerwald wrote:
> Hi,
>
>>> snd_pcm_mmap_commit() actually transfers the memory area prepared by
>> snd_pcm_mmap_begin(),
>>> it returns the 'count of transferred frames' which should be equal to the
>> number of frames
>>> returned by snd_pcm_mmap_begin()
>>>
>>> however, this identify is not checked and the number of frames prepared are
>> accounted for,
>>> not the number of frames commited -- this is wrong; the ALSA example codes
>> bothers to
>>> check snd_pcm_mmap_commit()'s returned number of frames
>>>
>>> this patch outputs a warning and uses the commited number of frames to
>> update the bytes
>>> read or written, resp.
>
>> It's not that easy, I think...
>> In case you get fewer frames written, you should retry the mmap_begin +
>> mmap_commit cycle but *without* calling pa_sink_render_into_full, and
>> only with the remaining frames. Right?
>
> ah, yes
>
> I think the question is: does it ever happen?
>
> currently, the code won't notice any glitches and does the wrong thing if
> sframes != frames
>
> the proposed code logs a warning and does the wrong thing if sframes !=
> frames
>
> the ALSA example just treats sframes != frames as an error -- probably
> that's the best thing to do (with some logging)?

Since we don't know if this ever happens, and if so, why, I think maybe 
act conservatively and just write something to the log?

And if this actually happens, we'll try to analyze it? Instead of guessing.

>
> regards, p.
>
>>> ---
>>>    src/modules/alsa/alsa-sink.c   |   11 +++++++++--
>>>    src/modules/alsa/alsa-source.c |   17 +++++++++++++----
>>>    2 files changed, 22 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
>>> index e256bbd..fc05232 100644
>>> --- a/src/modules/alsa/alsa-sink.c
>>> +++ b/src/modules/alsa/alsa-sink.c
>>> @@ -639,8 +639,7 @@ static int mmap_write(struct userdata *u, pa_usec_t
>> *sleep_usec, bool polled, bo
>>>
>>>                p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
>>>
>>> -            written = frames * u->frame_size;
>>> -            chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p,
>> written, true);
>>> +            chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p,
>> frames * u->frame_size, true);
>>>                chunk.length = pa_memblock_get_length(chunk.memblock);
>>>                chunk.index = 0;
>>>
>>> @@ -660,6 +659,14 @@ static int mmap_write(struct userdata *u, pa_usec_t
>> *sleep_usec, bool polled, bo
>>>
>>>                work_done = true;
>>>
>>> +            if (PA_UNLIKELY((snd_pcm_uframes_t) sframes != frames)) {
>>> +                PA_ONCE_BEGIN {
>>> +                    pa_log_warn("ALSA mmap write was set up up for %lu
>> frames, but unexpectedly commited %lu frames.\n",
>>> +                        (unsigned long) frames, (unsigned long) sframes);
>>> +                } PA_ONCE_END;
>>> +            }
>>> +
>>> +            written = sframes * u->frame_size;
>>>                u->write_count += written;
>>>                u->since_start += written;
>>>
>>> diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
>>> index 111c517..36e7585 100644
>>> --- a/src/modules/alsa/alsa-source.c
>>> +++ b/src/modules/alsa/alsa-source.c
>>> @@ -562,6 +562,7 @@ static int mmap_read(struct userdata *u, pa_usec_t
>> *sleep_usec, bool polled, boo
>>>                const snd_pcm_channel_area_t *areas;
>>>                snd_pcm_uframes_t offset, frames;
>>>                snd_pcm_sframes_t sframes;
>>> +            size_t got;
>>>
>>>                frames = (snd_pcm_uframes_t) (n_bytes / u->frame_size);
>>>    /*             pa_log_debug("%lu frames to read", (unsigned long) frames);
>> */
>>> @@ -613,16 +614,24 @@ static int mmap_read(struct userdata *u, pa_usec_t
>> *sleep_usec, bool polled, boo
>>>
>>>                work_done = true;
>>>
>>> -            u->read_count += frames * u->frame_size;
>>> +            if (PA_UNLIKELY((snd_pcm_uframes_t) sframes != frames)) {
>>> +                PA_ONCE_BEGIN {
>>> +                    pa_log_warn("ALSA mmap read was set up up for %lu
>> frames, but unexpectedly commited %lu frames.\n",
>>> +                        (unsigned long) frames, (unsigned long) sframes);
>>> +                } PA_ONCE_END;
>>> +            }
>>> +
>>> +            got = sframes * u->frame_size;
>>> +            u->read_count += got;
>>>
>>>    #ifdef DEBUG_TIMING
>>> -            pa_log_debug("Read %lu bytes (of possible %lu bytes)",
>> (unsigned long) (frames * u->frame_size), (unsigned long) n_bytes);
>>> +            pa_log_debug("Read %lu bytes (of possible %lu bytes)",
>> (unsigned long) got, (unsigned long) n_bytes);
>>>    #endif
>>>
>>> -            if ((size_t) frames * u->frame_size >= n_bytes)
>>> +            if (got >= n_bytes)
>>>                    break;
>>>
>>> -            n_bytes -= (size_t) frames * u->frame_size;
>>> +            n_bytes -= got;
>>>            }
>>>        }
>>>
>>>
>>
>>
>

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


More information about the pulseaudio-discuss mailing list