sim: To avoid system calls being interrupted when use host api

Signed-off-by: yintao <yintao@xiaomi.com>
This commit is contained in:
yintao 2023-08-23 12:36:36 +08:00 committed by Xiang Xiao
parent 6367f2469c
commit 9e43a4d31c
4 changed files with 130 additions and 140 deletions

View File

@ -33,6 +33,7 @@
#include <alsa/asoundlib.h>
#include "sim_internal.h"
#include "sim_offload.h"
/****************************************************************************
@ -161,40 +162,41 @@ static int sim_audio_config_format(struct sim_audio_s *priv, snd_pcm_t *pcm)
break;
}
ret = snd_pcm_hw_params_malloc(&hw_params);
ret = host_uninterruptible(snd_pcm_hw_params_malloc, &hw_params);
if (ret < 0)
{
return ret;
}
ret = snd_pcm_hw_params_any(pcm, hw_params);
ret = host_uninterruptible(snd_pcm_hw_params_any, pcm, hw_params);
if (ret < 0)
{
goto fail;
}
ret = snd_pcm_hw_params_set_access(pcm, hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED);
ret = host_uninterruptible(snd_pcm_hw_params_set_access, pcm,
hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (ret < 0)
{
goto fail;
}
ret = snd_pcm_hw_params_set_format(pcm, hw_params, format);
ret = host_uninterruptible(snd_pcm_hw_params_set_format, pcm,
hw_params, format);
if (ret < 0)
{
goto fail;
}
ret = snd_pcm_hw_params_set_rate(pcm, hw_params,
priv->sample_rate, 0);
ret = host_uninterruptible(snd_pcm_hw_params_set_rate, pcm,
hw_params, priv->sample_rate, 0);
if (ret < 0)
{
goto fail;
}
ret = snd_pcm_hw_params_set_channels(pcm, hw_params,
priv->channels);
ret = host_uninterruptible(snd_pcm_hw_params_set_channels, pcm,
hw_params, priv->channels);
if (ret < 0)
{
goto fail;
@ -203,8 +205,8 @@ static int sim_audio_config_format(struct sim_audio_s *priv, snd_pcm_t *pcm)
total_size = priv->nbuffers * priv->buffer_size;
pframes = priv->buffer_size / priv->frame_size;
ret = snd_pcm_hw_params_set_period_size_near(pcm, hw_params,
&pframes, NULL);
ret = host_uninterruptible(snd_pcm_hw_params_set_period_size_near,
pcm, hw_params, &pframes, NULL);
if (ret < 0)
{
goto fail;
@ -212,17 +214,17 @@ static int sim_audio_config_format(struct sim_audio_s *priv, snd_pcm_t *pcm)
priv->buffer_size = pframes * priv->frame_size;
priv->nbuffers = total_size / priv->buffer_size;
ret = snd_pcm_hw_params_set_periods_near(pcm, hw_params,
&priv->nbuffers, NULL);
ret = host_uninterruptible(snd_pcm_hw_params_set_periods_near, pcm,
hw_params, &priv->nbuffers, NULL);
if (ret < 0)
{
goto fail;
}
ret = snd_pcm_hw_params(pcm, hw_params);
ret = host_uninterruptible(snd_pcm_hw_params, pcm, hw_params);
fail:
snd_pcm_hw_params_free(hw_params);
host_uninterruptible_no_return(snd_pcm_hw_params_free, hw_params);
return ret;
}
@ -249,7 +251,6 @@ static void sim_audio_config_ops(struct sim_audio_s *priv, uint8_t fmt)
static int sim_audio_open(struct sim_audio_s *priv)
{
irqstate_t flags;
snd_pcm_t *pcm = NULL;
int direction;
int ret;
@ -259,15 +260,13 @@ static int sim_audio_open(struct sim_audio_s *priv)
return -ENXIO;
}
flags = up_irq_save();
direction = priv->playback ? SND_PCM_STREAM_PLAYBACK
: SND_PCM_STREAM_CAPTURE;
ret = snd_pcm_open(&pcm, "default", direction, 0);
ret = host_uninterruptible(snd_pcm_open, &pcm, "default", direction, 0);
if (ret < 0)
{
goto fail;
return ret;
}
ret = sim_audio_config_format(priv, pcm);
@ -276,7 +275,7 @@ static int sim_audio_open(struct sim_audio_s *priv)
goto fail;
}
ret = snd_pcm_start(pcm);
ret = host_uninterruptible(snd_pcm_start, pcm);
if (ret < 0)
{
goto fail;
@ -284,12 +283,12 @@ static int sim_audio_open(struct sim_audio_s *priv)
priv->pcm = pcm;
up_irq_restore(flags);
return 0;
fail:
snd_pcm_close(pcm);
up_irq_restore(flags);
host_uninterruptible(snd_pcm_close, pcm);
return ret;
}
@ -300,7 +299,7 @@ static int sim_audio_close(struct sim_audio_s *priv)
return -ENXIO;
}
snd_pcm_close(priv->pcm);
host_uninterruptible(snd_pcm_close, priv->pcm);
priv->pcm = NULL;
@ -380,15 +379,17 @@ static int sim_audio_getcaps(struct audio_lowerhalf_s *dev, int type,
switch (caps->ac_format.hw)
{
case AUDIO_FU_VOLUME:
snd_mixer_selem_get_playback_volume(priv->volume,
SND_MIXER_SCHN_UNKNOWN,
&val);
host_uninterruptible(snd_mixer_selem_get_playback_volume,
priv->volume,
SND_MIXER_SCHN_UNKNOWN,
&val);
caps->ac_controls.w = val;
break;
case AUDIO_FU_INP_GAIN:
snd_mixer_selem_get_capture_volume(priv->volume,
SND_MIXER_SCHN_MONO,
&val);
host_uninterruptible(snd_mixer_selem_get_capture_volume,
priv->volume,
SND_MIXER_SCHN_MONO,
&val);
caps->ac_controls.w = val;
break;
default:
@ -430,12 +431,14 @@ static int sim_audio_configure(struct audio_lowerhalf_s *dev,
switch (caps->ac_format.hw)
{
case AUDIO_FU_VOLUME:
ret = snd_mixer_selem_set_playback_volume_all(priv->volume,
caps->ac_controls.hw[0]);
ret = host_uninterruptible(
snd_mixer_selem_set_playback_volume_all,
priv->volume, caps->ac_controls.hw[0]);
break;
case AUDIO_FU_INP_GAIN:
ret = snd_mixer_selem_set_capture_volume_all(priv->volume,
caps->ac_controls.hw[0]);
ret = host_uninterruptible(
snd_mixer_selem_set_capture_volume_all,
priv->volume, caps->ac_controls.hw[0]);
break;
default:
ret = -ENOTTY;
@ -632,7 +635,7 @@ static int sim_alsa_get_latency(struct audio_lowerhalf_s *dev,
return -ENXIO;
}
ret = snd_pcm_delay(priv->pcm, latency);
ret = host_uninterruptible(snd_pcm_delay, priv->pcm, latency);
if (ret < 0)
{
return ret;
@ -817,7 +820,8 @@ static int sim_audio_process_playback(struct sim_audio_s *priv,
aux->curbyte += ret;
ret = snd_pcm_writei(priv->pcm, out, outsize / priv->frame_size);
ret = host_uninterruptible(snd_pcm_writei, priv->pcm, out,
outsize / priv->frame_size);
ret *= priv->frame_size;
}
@ -845,7 +849,8 @@ static int sim_audio_process_capture(struct sim_audio_s *priv,
int frames = 0;
int ret;
frames = snd_pcm_readi(priv->pcm, apb->samp, expect);
frames = host_uninterruptible(snd_pcm_readi, priv->pcm,
apb->samp, expect);
if (frames < 0)
{
return frames;
@ -927,7 +932,7 @@ static void sim_audio_process(struct sim_audio_s *priv)
/ priv->frame_size;
}
avail = snd_pcm_avail(priv->pcm);
avail = host_uninterruptible(snd_pcm_avail, priv->pcm);
if (avail < expect)
{
return;
@ -973,7 +978,7 @@ static void sim_audio_process(struct sim_audio_s *priv)
if (final)
{
snd_pcm_drain(priv->pcm);
host_uninterruptible(snd_pcm_drain, priv->pcm);
#ifdef CONFIG_AUDIO_MULTI_SESSION
sim_audio_stop(&priv->dev, NULL);
#else
@ -988,46 +993,47 @@ out:
if (ret == -EPIPE)
{
awarn("ALSA buffer xrun.\n");
snd_pcm_prepare(priv->pcm);
snd_pcm_start(priv->pcm);
host_uninterruptible(snd_pcm_prepare, priv->pcm);
host_uninterruptible(snd_pcm_start, priv->pcm);
}
else if (ret != -EAGAIN)
{
aerr("pcm writei/readi failed %d, %s\n", ret, snd_strerror(ret));
aerr("pcm writei/readi failed %d, %s\n", ret,
host_uninterruptible(snd_strerror, ret));
}
}
static int sim_mixer_open(struct sim_audio_s *priv)
{
snd_mixer_selem_id_t *sid = NULL;
irqstate_t flags = up_irq_save();
int ret;
ret = snd_mixer_open(&priv->mixer, 0);
ret = host_uninterruptible(snd_mixer_open, &priv->mixer, 0);
if (ret < 0)
{
goto fail;
}
ret = snd_mixer_attach(priv->mixer, "default");
ret = host_uninterruptible(snd_mixer_attach, priv->mixer, "default");
if (ret < 0)
{
goto fail;
}
ret = snd_mixer_selem_register(priv->mixer, NULL, NULL);
ret = host_uninterruptible(snd_mixer_selem_register,
priv->mixer, NULL, NULL);
if (ret < 0)
{
goto fail;
}
ret = snd_mixer_load(priv->mixer);
ret = host_uninterruptible(snd_mixer_load, priv->mixer);
if (ret < 0)
{
goto fail;
}
ret = snd_mixer_selem_id_malloc(&sid);
ret = host_uninterruptible(snd_mixer_selem_id_malloc, &sid);
if (ret < 0)
{
goto fail;
@ -1035,17 +1041,20 @@ static int sim_mixer_open(struct sim_audio_s *priv)
if (priv->playback)
{
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, "Master");
host_uninterruptible_no_return(snd_mixer_selem_id_set_index, sid, 0);
host_uninterruptible_no_return(snd_mixer_selem_id_set_name,
sid, "Master");
priv->volume = snd_mixer_find_selem(priv->mixer, sid);
snd_mixer_selem_id_free(sid);
priv->volume = host_uninterruptible(snd_mixer_find_selem,
priv->mixer, sid);
host_uninterruptible_no_return(snd_mixer_selem_id_free, sid);
if (!priv->volume)
{
goto fail;
}
ret = snd_mixer_selem_set_playback_volume_range(priv->volume, 0, 1000);
ret = host_uninterruptible(snd_mixer_selem_set_playback_volume_range,
priv->volume, 0, 1000);
if (ret < 0)
{
goto fail;
@ -1053,28 +1062,29 @@ static int sim_mixer_open(struct sim_audio_s *priv)
}
else
{
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, "Capture");
host_uninterruptible_no_return(snd_mixer_selem_id_set_index, sid, 0);
host_uninterruptible_no_return(snd_mixer_selem_id_set_name,
sid, "Capture");
priv->volume = snd_mixer_find_selem(priv->mixer, sid);
snd_mixer_selem_id_free(sid);
priv->volume = host_uninterruptible(snd_mixer_find_selem,
priv->mixer, sid);
host_uninterruptible_no_return(snd_mixer_selem_id_free, sid);
if (!priv->volume)
{
goto fail;
}
ret = snd_mixer_selem_set_capture_volume_range(priv->volume, 0, 1000);
ret = host_uninterruptible(snd_mixer_selem_set_capture_volume_range,
priv->volume, 0, 1000);
if (ret < 0)
{
goto fail;
}
}
up_irq_restore(flags);
return 0;
fail:
snd_mixer_close(priv->mixer);
up_irq_restore(flags);
host_uninterruptible(snd_mixer_close, priv->mixer);
priv->mixer = NULL;
return 0;
}

View File

@ -52,9 +52,6 @@ static atomic_int g_uordblks;
* Public Functions
****************************************************************************/
extern uint64_t up_irq_save(void);
extern void up_irq_restore(uint64_t flags);
/****************************************************************************
* Name: host_allocheap
*
@ -65,21 +62,19 @@ extern void up_irq_restore(uint64_t flags);
void *host_allocheap(size_t sz)
{
uint64_t flags = up_irq_save();
void *p;
#if defined(CONFIG_HOST_MACOS) && defined(CONFIG_HOST_ARM64)
/* see: https://developer.apple.com/forums/thread/672804 */
p = mmap(NULL, sz, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_SHARED, -1, 0);
p = host_uninterruptible(mmap, NULL, sz, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_SHARED, -1, 0);
#else
p = mmap(NULL, sz, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0);
p = host_uninterruptible(mmap, NULL, sz,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0);
#endif
up_irq_restore(flags);
if (p == MAP_FAILED)
{
return NULL;
@ -98,14 +93,11 @@ void *host_allocheap(size_t sz)
void host_freeheap(void *mem)
{
uint64_t flags = up_irq_save();
munmap(mem, 0);
up_irq_restore(flags);
host_uninterruptible(munmap, mem, 0);
}
void *host_allocshmem(const char *name, size_t size, int master)
{
uint64_t flags = up_irq_save();
void *mem;
int oflag;
int ret;
@ -117,10 +109,9 @@ void *host_allocshmem(const char *name, size_t size, int master)
oflag |= O_CREAT | O_TRUNC;
}
fd = shm_open(name, oflag, S_IRUSR | S_IWUSR);
fd = host_uninterruptible(shm_open, name, oflag, S_IRUSR | S_IWUSR);
if (fd < 0)
{
up_irq_restore(flags);
return NULL;
}
@ -128,20 +119,19 @@ void *host_allocshmem(const char *name, size_t size, int master)
{
/* Avoid the second slave instance open successfully */
shm_unlink(name);
host_uninterruptible(shm_unlink, name);
}
ret = ftruncate(fd, size);
ret = host_uninterruptible(ftruncate, fd, size);
if (ret < 0)
{
up_irq_restore(flags);
close(fd);
host_uninterruptible(close, fd);
return NULL;
}
mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd); /* Don't need keep fd any more once the memory get mapped */
up_irq_restore(flags);
mem = host_uninterruptible(mmap, NULL, size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
host_uninterruptible(close, fd); /* Don't need keep fd any more once the memory get mapped */
if (mem == MAP_FAILED)
{
return NULL;
@ -152,23 +142,20 @@ void *host_allocshmem(const char *name, size_t size, int master)
void host_freeshmem(void *mem)
{
uint64_t flags = up_irq_save();
munmap(mem, 0);
up_irq_restore(flags);
host_uninterruptible(munmap, mem, 0);
}
size_t host_mallocsize(void *mem)
{
#ifdef __APPLE__
return malloc_size(mem);
return host_uninterruptible(malloc_size, mem);
#else
return malloc_usable_size(mem);
return host_uninterruptible(malloc_usable_size, mem);
#endif
}
void *host_memalign(size_t alignment, size_t size)
{
uint64_t flags = up_irq_save();
void *p;
int error;
@ -177,18 +164,15 @@ void *host_memalign(size_t alignment, size_t size)
alignment = sizeof(void *);
}
error = posix_memalign(&p, alignment, size);
error = host_uninterruptible(posix_memalign, &p, alignment, size);
if (error != 0)
{
up_irq_restore(flags);
return NULL;
}
size = host_mallocsize(p);
g_aordblks += 1;
g_uordblks += size;
up_irq_restore(flags);
atomic_fetch_add(&g_aordblks, 1);
atomic_fetch_add(&g_uordblks, size);
return p;
}
@ -196,24 +180,20 @@ void *host_memalign(size_t alignment, size_t size)
void host_free(void *mem)
{
size_t size;
uint64_t flags;
if (mem == NULL)
{
return;
}
flags = up_irq_save();
size = host_mallocsize(mem);
g_aordblks -= 1;
g_uordblks -= size;
free(mem);
up_irq_restore(flags);
atomic_fetch_sub(&g_aordblks, 1);
atomic_fetch_sub(&g_uordblks, size);
host_uninterruptible_no_return(free, mem);
}
void *host_realloc(void *oldmem, size_t size)
{
uint64_t flags;
size_t oldsize;
void *mem;
@ -222,27 +202,21 @@ void *host_realloc(void *oldmem, size_t size)
return host_memalign(sizeof(void *), size);
}
flags = up_irq_save();
oldsize = host_mallocsize(oldmem);
mem = realloc(oldmem, size);
mem = host_uninterruptible(realloc, oldmem, size);
if (mem == NULL)
{
up_irq_restore(flags);
return NULL;
}
size = host_mallocsize(mem);
g_uordblks -= oldsize;
g_uordblks += size;
up_irq_restore(flags);
atomic_fetch_add(&g_uordblks, size - oldsize);
return mem;
}
void host_mallinfo(int *aordblks, int *uordblks)
{
*aordblks = g_aordblks;
*uordblks = g_uordblks;
*aordblks = atomic_load(&g_aordblks);
*uordblks = atomic_load(&g_uordblks);
}

View File

@ -52,8 +52,6 @@ void __gcov_dump(void);
* Public Functions
****************************************************************************/
extern uint64_t up_irq_save(void);
extern void up_irq_restore(uint64_t flags);
extern int backtrace(void **array, int size);
/****************************************************************************
@ -68,19 +66,15 @@ extern int backtrace(void **array, int size);
void host_abort(int status)
{
uint64_t flags = up_irq_save();
#ifdef CONFIG_ARCH_COVERAGE
/* Dump gcov data. */
__gcov_dump();
host_uninterruptible_no_return(__gcov_dump);
#endif
/* exit the simulation */
exit(status);
up_irq_restore(flags);
host_uninterruptible_no_return(exit, status);
}
/****************************************************************************
@ -99,13 +93,7 @@ int host_backtrace(void** array, int size)
#ifdef CONFIG_WINDOWS_CYGWIN
return 0;
#else
uint64_t flags = up_irq_save();
int ret;
ret = backtrace(array, size);
up_irq_restore(flags);
return ret;
return host_uninterruptible(backtrace, array, size);
#endif
}
@ -130,7 +118,6 @@ int host_system(char *buf, size_t len, const char *fmt, ...)
{
FILE *fp;
int ret;
uint64_t flags;
char cmd[512];
va_list vars;
@ -144,21 +131,18 @@ int host_system(char *buf, size_t len, const char *fmt, ...)
if (buf == NULL)
{
ret = system(cmd);
ret = host_uninterruptible(system, cmd);
}
else
{
flags = up_irq_save();
fp = popen(cmd, "r");
fp = host_uninterruptible(popen, cmd, "r");
if (fp == NULL)
{
up_irq_restore(flags);
return -errno;
}
ret = fread(buf, sizeof(char), len, fp);
pclose(fp);
up_irq_restore(flags);
ret = host_uninterruptible(fread, buf, 1, len, fp);
host_uninterruptible(pclose, fp);
}
return ret < 0 ? -errno : ret;
@ -178,10 +162,10 @@ void host_init_cwd(void)
/* Get the absolute path of the executable file */
# ifdef CONFIG_HOST_LINUX
len = readlink("/proc/self/exe", path, len);
len = host_uninterruptible(readlink, "/proc/self/exe", path, len);
if (len < 0)
{
perror("readlink failed");
host_uninterruptible_no_return(perror, "readlink failed");
return;
}
# else
@ -195,7 +179,7 @@ void host_init_cwd(void)
path[len] = '\0';
name = strrchr(path, '/');
*++name = '\0';
chdir(path);
host_uninterruptible(chdir, path);
}
#endif
@ -218,7 +202,8 @@ pid_t host_posix_spawn(const char *path,
argv = default_argv;
}
ret = posix_spawn(&pid, path, NULL, NULL, argv, envp);
ret = host_uninterruptible(posix_spawn, &pid, path,
NULL, NULL, argv, envp);
return ret > 0 ? -ret : pid;
}
@ -230,6 +215,6 @@ int host_waitpid(pid_t pid)
{
int status;
pid = waitpid(pid, &status, 0);
pid = host_uninterruptible(waitpid, pid, &status, 0);
return pid < 0 ? -errno : status;
}

View File

@ -120,6 +120,27 @@
} \
while (0)
#define host_uninterruptible(func, ...) \
({ \
extern uint64_t up_irq_save(void); \
extern void up_irq_restore(uint64_t flags); \
uint64_t flags_ = up_irq_save(); \
typeof(func(__VA_ARGS__)) ret_ = func(__VA_ARGS__); \
up_irq_restore(flags_); \
ret_; \
})
#define host_uninterruptible_no_return(func, ...) \
do \
{ \
extern uint64_t up_irq_save(void); \
extern void up_irq_restore(uint64_t flags); \
uint64_t flags_ = up_irq_save(); \
func(__VA_ARGS__); \
up_irq_restore(flags_); \
} \
while (0)
/* File System Definitions **************************************************/
/* These definitions characterize the compressed filesystem image */