pcm: dmix: make lockless operation optional

The recently reported (but a long-standing) bug about the
unconditional semaphore usage in the dmix implies that basically we've
had no problem with the locking in the practical usages over years.
Although the lockless operation has a clear merit, it's a much higher
CPU usage (especially on some uncached pages), and it might lead to a
potential deadlock in theory (which is hard to reproduce at will,
though).

This patch introduces a new configure option "--enable-lockless-dmix"
or "--disable-lockless-dmix" to let user choose the default dmix
operation mode.  The usage of the lockless mixing has been already
conditionally enabled via asoundrc and card config
"direct_memory_access", so we just need to set the default value based
on it.

In this patch, the default is set off to the lockless mixing, i.e. the
generic mixing is chosen.  It makes more sense from the performance
POV.  For any users who still require the lockless operation, it can
be enabled either via configure option or the asoundrc.

The magic number used in the shmem is also changed depending on the
operation mode.  It's just for safety, not to conflict both operation
modes with each other.

Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2020-06-19 18:57:05 +02:00
parent 877bdf95fd
commit 4759865c86
2 changed files with 26 additions and 3 deletions

View file

@ -629,6 +629,19 @@ if test "$build_pcm_mmap_emul" = "yes"; then
AC_DEFINE([BUILD_PCM_PLUGIN_MMAP_EMUL], "1", [Build PCM mmap-emul plugin])
fi
if test "$build_pcm_dmix" = "yes"; then
AC_MSG_CHECKING(for default lockless dmix)
AC_ARG_ENABLE(lockless-dmix,
AS_HELP_STRING([--enable-lockless-dmix],
[use lockless dmix as default on x86]),
lockless_dmix="$enableval", lockless_dmix="no")
if test "$lockless_dmix" = "yes"; then
AC_MSG_RESULT(yes)
AC_DEFINE([LOCKLESS_DMIX_DEFAULT], "1", [Lockless dmix as default])
else
AC_MSG_RESULT(no)
fi
fi
dnl Create PCM plugin symbol list for static library
rm -f "$srcdir"/src/pcm/pcm_symbols_list.c

View file

@ -82,7 +82,13 @@ int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix)
return 0;
}
#define SND_PCM_DIRECT_MAGIC (0xa15ad300 + sizeof(snd_pcm_direct_share_t))
static unsigned int snd_pcm_direct_magic(snd_pcm_direct_t *dmix)
{
if (!dmix->direct_memory_access)
return 0xa15ad300 + sizeof(snd_pcm_direct_share_t);
else
return 0xb15ad300 + sizeof(snd_pcm_direct_share_t);
}
/*
* global shared memory area
@ -132,10 +138,10 @@ retryget:
buf.shm_perm.gid = dmix->ipc_gid;
shmctl(dmix->shmid, IPC_SET, &buf);
}
dmix->shmptr->magic = SND_PCM_DIRECT_MAGIC;
dmix->shmptr->magic = snd_pcm_direct_magic(dmix);
return 1;
} else {
if (dmix->shmptr->magic != SND_PCM_DIRECT_MAGIC) {
if (dmix->shmptr->magic != snd_pcm_direct_magic(dmix)) {
snd_pcm_direct_shm_discard(dmix);
return -EINVAL;
}
@ -1892,7 +1898,11 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
rec->slowptr = 1;
rec->max_periods = 0;
rec->var_periodsize = 0;
#ifdef LOCKLESS_DMIX_DEFAULT
rec->direct_memory_access = 1;
#else
rec->direct_memory_access = 0;
#endif
rec->hw_ptr_alignment = SND_PCM_HW_PTR_ALIGNMENT_AUTO;
rec->tstamp_type = -1;