diff options
author | Arnd Bergmann <arnd@arndb.de> | 2016-06-17 11:10:32 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2016-06-17 16:56:13 -0400 |
commit | 3915bf2946520ace5bcc8104717a3cb0452d7430 (patch) | |
tree | 031c5d4fa69ee97585d8c0aa8b8ad163b06dee21 | |
parent | d169133889090903d9feb968deb9fa01240a58f5 (diff) |
ALSA: seq_timer: use monotonic times internally
The sequencer client manager reports timestamps in units of unsigned
32-bit seconds/nanoseconds, but that does not suffer from the y2038
overflow because it stores only the delta since the 'last_update'
time was recorded.
However, the use of the do_gettimeofday() function is problematic
and we have to replace it to avoid the overflow on on 32-bit
architectures.
This uses 'struct timespec64' to record 'last_update', and changes
the code to use monotonic timestamps that do not suffer from leap
seconds and settimeofday updates.
As a side-effect, the code can now use the timespec64_sub() helper
and become more readable and also avoid a multiplication to convert
from microseconds to nanoseconds.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/core/seq/seq_timer.c | 23 | ||||
-rw-r--r-- | sound/core/seq/seq_timer.h | 2 |
2 files changed, 10 insertions, 15 deletions
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index 293104926098..dcc102813aef 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c | |||
@@ -165,7 +165,7 @@ static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri, | |||
165 | snd_seq_timer_update_tick(&tmr->tick, resolution); | 165 | snd_seq_timer_update_tick(&tmr->tick, resolution); |
166 | 166 | ||
167 | /* register actual time of this timer update */ | 167 | /* register actual time of this timer update */ |
168 | do_gettimeofday(&tmr->last_update); | 168 | ktime_get_ts64(&tmr->last_update); |
169 | 169 | ||
170 | spin_unlock_irqrestore(&tmr->lock, flags); | 170 | spin_unlock_irqrestore(&tmr->lock, flags); |
171 | 171 | ||
@@ -392,7 +392,7 @@ static int seq_timer_start(struct snd_seq_timer *tmr) | |||
392 | return -EINVAL; | 392 | return -EINVAL; |
393 | snd_timer_start(tmr->timeri, tmr->ticks); | 393 | snd_timer_start(tmr->timeri, tmr->ticks); |
394 | tmr->running = 1; | 394 | tmr->running = 1; |
395 | do_gettimeofday(&tmr->last_update); | 395 | ktime_get_ts64(&tmr->last_update); |
396 | return 0; | 396 | return 0; |
397 | } | 397 | } |
398 | 398 | ||
@@ -420,7 +420,7 @@ static int seq_timer_continue(struct snd_seq_timer *tmr) | |||
420 | } | 420 | } |
421 | snd_timer_start(tmr->timeri, tmr->ticks); | 421 | snd_timer_start(tmr->timeri, tmr->ticks); |
422 | tmr->running = 1; | 422 | tmr->running = 1; |
423 | do_gettimeofday(&tmr->last_update); | 423 | ktime_get_ts64(&tmr->last_update); |
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
426 | 426 | ||
@@ -444,17 +444,12 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr) | |||
444 | spin_lock_irqsave(&tmr->lock, flags); | 444 | spin_lock_irqsave(&tmr->lock, flags); |
445 | cur_time = tmr->cur_time; | 445 | cur_time = tmr->cur_time; |
446 | if (tmr->running) { | 446 | if (tmr->running) { |
447 | struct timeval tm; | 447 | struct timespec64 tm; |
448 | int usec; | 448 | |
449 | do_gettimeofday(&tm); | 449 | ktime_get_ts64(&tm); |
450 | usec = (int)(tm.tv_usec - tmr->last_update.tv_usec); | 450 | tm = timespec64_sub(tm, tmr->last_update); |
451 | if (usec < 0) { | 451 | cur_time.tv_nsec = tm.tv_nsec; |
452 | cur_time.tv_nsec += (1000000 + usec) * 1000; | 452 | cur_time.tv_sec = tm.tv_sec; |
453 | cur_time.tv_sec += tm.tv_sec - tmr->last_update.tv_sec - 1; | ||
454 | } else { | ||
455 | cur_time.tv_nsec += usec * 1000; | ||
456 | cur_time.tv_sec += tm.tv_sec - tmr->last_update.tv_sec; | ||
457 | } | ||
458 | snd_seq_sanity_real_time(&cur_time); | 453 | snd_seq_sanity_real_time(&cur_time); |
459 | } | 454 | } |
460 | spin_unlock_irqrestore(&tmr->lock, flags); | 455 | spin_unlock_irqrestore(&tmr->lock, flags); |
diff --git a/sound/core/seq/seq_timer.h b/sound/core/seq/seq_timer.h index 88dfb71805ae..9506b661fe5b 100644 --- a/sound/core/seq/seq_timer.h +++ b/sound/core/seq/seq_timer.h | |||
@@ -52,7 +52,7 @@ struct snd_seq_timer { | |||
52 | unsigned int skew; | 52 | unsigned int skew; |
53 | unsigned int skew_base; | 53 | unsigned int skew_base; |
54 | 54 | ||
55 | struct timeval last_update; /* time of last clock update, used for interpolation */ | 55 | struct timespec64 last_update; /* time of last clock update, used for interpolation */ |
56 | 56 | ||
57 | spinlock_t lock; | 57 | spinlock_t lock; |
58 | }; | 58 | }; |