[alsa-devel] POSIX clocks and ALSA
Jaroslav Kysela
perex at perex.cz
Mon Nov 26 15:51:02 CET 2007
On Mon, 26 Nov 2007, Heikki Lindholm wrote:
> I had a look at the proposal and the thread at
> http://thread.gmane.org/gmane.linux.alsa.devel/45237/focus=45573
My initial implementation following proposal is bellow for review and
comments. I also changed timestamps for ALSA timers to use monotonic
clocks (can be switched back using a module parameter).
Jaroslav
diff -r 5e8cab953031 core/pcm_lib.c
--- a/core/pcm_lib.c Mon Nov 26 09:00:56 2007 +0100
+++ b/core/pcm_lib.c Mon Nov 26 14:50:01 2007 +0100
@@ -188,7 +188,7 @@ static inline int snd_pcm_update_hw_ptr_
snd_pcm_sframes_t delta;
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_MMAP)
- getnstimeofday((struct timespec *)&runtime->status->tstamp);
+ snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
if (pos == SNDRV_PCM_POS_XRUN) {
xrun(substream);
diff -r 5e8cab953031 core/pcm_native.c
--- a/core/pcm_native.c Mon Nov 26 09:00:56 2007 +0100
+++ b/core/pcm_native.c Mon Nov 26 15:19:22 2007 +0100
@@ -598,9 +598,9 @@ int snd_pcm_status(struct snd_pcm_substr
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_MMAP)
status->tstamp = runtime->status->tstamp;
else
- getnstimeofday(&status->tstamp);
+ snd_pcm_gettime(runtime, &status->tstamp);
} else
- getnstimeofday(&status->tstamp);
+ snd_pcm_gettime(runtime, &status->tstamp);
status->appl_ptr = runtime->control->appl_ptr;
status->hw_ptr = runtime->status->hw_ptr;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -688,7 +688,7 @@ static void snd_pcm_trigger_tstamp(struc
if (runtime->trigger_master == NULL)
return;
if (runtime->trigger_master == substream) {
- getnstimeofday(&runtime->trigger_tstamp);
+ snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
} else {
snd_pcm_trigger_tstamp(runtime->trigger_master);
runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp;
@@ -2519,6 +2519,21 @@ static int snd_pcm_sync_ptr(struct snd_p
return -EFAULT;
return 0;
}
+
+static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int arg;
+
+ if (get_user(arg, _arg))
+ return -EFAULT;
+ if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
+ return -EINVAL;
+ runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
+ if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
+ runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
+ return 0;
+}
static int snd_pcm_common_ioctl1(struct file *file,
struct snd_pcm_substream *substream,
@@ -2531,8 +2546,8 @@ static int snd_pcm_common_ioctl1(struct
return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
case SNDRV_PCM_IOCTL_INFO:
return snd_pcm_info_user(substream, arg);
- case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */
- return 0;
+ case SNDRV_PCM_IOCTL_TSTAMP:
+ return snd_pcm_tstamp(substream, arg);
case SNDRV_PCM_IOCTL_HW_REFINE:
return snd_pcm_hw_refine_user(substream, arg);
case SNDRV_PCM_IOCTL_HW_PARAMS:
diff -r 5e8cab953031 core/timer.c
--- a/core/timer.c Mon Nov 26 09:00:56 2007 +0100
+++ b/core/timer.c Mon Nov 26 14:59:33 2007 +0100
@@ -44,11 +44,14 @@
#endif
static int timer_limit = DEFAULT_TIMER_LIMIT;
+static int timer_tstamp_monotonic = 1;
MODULE_AUTHOR("Jaroslav Kysela <perex at perex.cz>, Takashi Iwai <tiwai at suse.de>");
MODULE_DESCRIPTION("ALSA timer interface");
MODULE_LICENSE("GPL");
module_param(timer_limit, int, 0444);
MODULE_PARM_DESC(timer_limit, "Maximum global timers in system.");
+module_param(timer_tstamp_monotonic, int, 0444);
+MODULE_PARM_DESC(timer_tstamp_monotonic, "Use posix monotonic clock source for timestamps (default).");
struct snd_timer_user {
struct snd_timer_instance *timeri;
@@ -381,7 +384,10 @@ static void snd_timer_notify1(struct snd
struct snd_timer_instance *ts;
struct timespec tstamp;
- getnstimeofday(&tstamp);
+ if (timer_tstamp_monotonic)
+ do_posix_clock_monotonic_gettime(&tstamp);
+ else
+ getnstimeofday(&tstamp);
snd_assert(event >= SNDRV_TIMER_EVENT_START &&
event <= SNDRV_TIMER_EVENT_PAUSE, return);
if (event == SNDRV_TIMER_EVENT_START ||
@@ -1182,8 +1188,12 @@ static void snd_timer_user_tinterrupt(st
spin_unlock(&tu->qlock);
return;
}
- if (tu->last_resolution != resolution || ticks > 0)
- getnstimeofday(&tstamp);
+ if (tu->last_resolution != resolution || ticks > 0) {
+ if (timer_tstamp_monotonic)
+ do_posix_clock_monotonic_gettime(&tstamp);
+ else
+ getnstimeofday(&tstamp);
+ }
if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
tu->last_resolution != resolution) {
r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
diff -r 5e8cab953031 include/asound.h
--- a/include/asound.h Mon Nov 26 09:00:56 2007 +0100
+++ b/include/asound.h Mon Nov 26 15:02:57 2007 +0100
@@ -435,6 +435,13 @@ struct snd_xfern {
};
enum {
+ SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
+ SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY1, /* for compatibility, equal to zero */
+ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */
+ SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+};
+
+enum {
SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct snd_pcm_info),
SNDRV_PCM_IOCTL_TSTAMP = _IOW('A', 0x02, int),
diff -r 5e8cab953031 include/pcm.h
--- a/include/pcm.h Mon Nov 26 09:00:56 2007 +0100
+++ b/include/pcm.h Mon Nov 26 15:20:22 2007 +0100
@@ -323,6 +323,7 @@ struct snd_pcm_runtime {
/* -- timer -- */
unsigned int timer_resolution; /* timer resolution */
+ int tstamp_type; /* timestamp type */
/* -- DMA -- */
unsigned char *dma_area; /* DMA area */
@@ -952,6 +953,15 @@ void snd_pcm_timer_init(struct snd_pcm_s
void snd_pcm_timer_init(struct snd_pcm_substream *substream);
void snd_pcm_timer_done(struct snd_pcm_substream *substream);
+static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime,
+ struct timespec *tv)
+{
+ if (runtime->tstamp_type == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
+ do_posix_clock_monotonic_gettime(tv);
+ else
+ getnstimeofday(tv);
+}
+
/*
* Memory
*/
-----
Jaroslav Kysela <perex at perex.cz>
Linux Kernel Sound Maintainer
ALSA Project
More information about the Alsa-devel
mailing list