pulseaudio/src/pulsecore/core-rtclock.c
poljar (Damir Jelić) d806b19714 Remove pa_bool_t and replace it with bool.
commands used for this (executed from the pulseaudio/src directory):
    find . -regex '\(.*\.[hc]\|.*\.cc\|.*\.m4\)' -not -name 'macro.h' \
        -a -not -name 'reserve.[ch]' -a -not -name 'reserve-monitor.[ch]' \
        -a -not -name 'glib-mainloop.c' -a -not -name 'gkt-test.c' \
        -a -not -name 'glib-mainloop.c' -a -not -name 'gkt-test.c' \
        -a -not -name 'poll-win32.c' -a -not -name 'thread-win32.c' \
        -a -not -name 'dllmain.c' -a -not -name 'gconf-helper.c' \
        -exec sed -i -e 's/\bpa_bool_t\b/bool/g' \
        -e 's/\bTRUE\b/true/g' -e 's/\bFALSE\b/false/g' {} \;

and:
    sed -i -e '181,194!s/\bpa_bool_t\b/bool/' \
        -e '181,194!s/\bTRUE\b/true/' -e \
        '181,194!s/\bFALSE\b/false/' pulsecore/macro.h
2013-07-04 12:25:30 +03:00

269 lines
6.4 KiB
C

/***
This file is part of PulseAudio.
Copyright 2004-2006 Lennart Poettering
Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
***/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef OS_IS_DARWIN
#define _POSIX_C_SOURCE 1
#endif
#include <stddef.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
#ifdef OS_IS_DARWIN
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <unistd.h>
#endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#include <pulse/timeval.h>
#include <pulsecore/macro.h>
#include <pulsecore/core-error.h>
#include "core-rtclock.h"
#ifdef OS_IS_WIN32
static int64_t counter_freq = 0;
#endif
pa_usec_t pa_rtclock_age(const struct timeval *tv) {
struct timeval now;
pa_assert(tv);
return pa_timeval_diff(pa_rtclock_get(&now), tv);
}
struct timeval *pa_rtclock_get(struct timeval *tv) {
#if defined(OS_IS_DARWIN)
uint64_t val, abs_time = mach_absolute_time();
Nanoseconds nanos;
nanos = AbsoluteToNanoseconds(*(AbsoluteTime *) &abs_time);
val = *(uint64_t *) &nanos;
tv->tv_sec = val / PA_NSEC_PER_SEC;
tv->tv_usec = (val % PA_NSEC_PER_SEC) / PA_NSEC_PER_USEC;
return tv;
#elif defined(HAVE_CLOCK_GETTIME)
struct timespec ts;
#ifdef CLOCK_MONOTONIC
/* No locking or atomic ops for no_monotonic here */
static bool no_monotonic = false;
if (!no_monotonic)
if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
no_monotonic = true;
if (no_monotonic)
#endif /* CLOCK_MONOTONIC */
pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
pa_assert(tv);
tv->tv_sec = ts.tv_sec;
tv->tv_usec = ts.tv_nsec / PA_NSEC_PER_USEC;
return tv;
#elif defined(OS_IS_WIN32)
if (counter_freq > 0) {
LARGE_INTEGER count;
pa_assert_se(QueryPerformanceCounter(&count));
tv->tv_sec = count.QuadPart / counter_freq;
tv->tv_usec = (count.QuadPart % counter_freq) * PA_USEC_PER_SEC / counter_freq;
return tv;
}
#endif /* HAVE_CLOCK_GETTIME */
return pa_gettimeofday(tv);
}
bool pa_rtclock_hrtimer(void) {
#if defined (OS_IS_DARWIN)
mach_timebase_info_data_t tbi;
uint64_t time_nsec;
mach_timebase_info(&tbi);
/* nsec = nticks * (N/D) - we want 1 tick == resolution !? */
time_nsec = tbi.numer / tbi.denom;
return time_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
#elif defined(HAVE_CLOCK_GETTIME)
struct timespec ts;
#ifdef CLOCK_MONOTONIC
if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0)
return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
#endif /* CLOCK_MONOTONIC */
pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0);
return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
#elif defined(OS_IS_WIN32)
if (counter_freq > 0)
return counter_freq >= (int64_t) (PA_USEC_PER_SEC/PA_HRTIMER_THRESHOLD_USEC);
#endif /* HAVE_CLOCK_GETTIME */
return false;
}
#define TIMER_SLACK_NS (int) ((500 * PA_NSEC_PER_USEC))
void pa_rtclock_hrtimer_enable(void) {
#ifdef PR_SET_TIMERSLACK
int slack_ns;
if ((slack_ns = prctl(PR_GET_TIMERSLACK, 0, 0, 0, 0)) < 0) {
pa_log_info("PR_GET_TIMERSLACK/PR_SET_TIMERSLACK not supported.");
return;
}
pa_log_debug("Timer slack is set to %i us.", (int) (slack_ns/PA_NSEC_PER_USEC));
if (slack_ns > TIMER_SLACK_NS) {
slack_ns = TIMER_SLACK_NS;
pa_log_debug("Setting timer slack to %i us.", (int) (slack_ns/PA_NSEC_PER_USEC));
if (prctl(PR_SET_TIMERSLACK, slack_ns, 0, 0, 0) < 0) {
pa_log_warn("PR_SET_TIMERSLACK failed: %s", pa_cstrerror(errno));
return;
}
}
#elif defined(OS_IS_WIN32)
LARGE_INTEGER freq;
pa_assert_se(QueryPerformanceFrequency(&freq));
counter_freq = freq.QuadPart;
#endif
}
struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) {
struct timeval wc_now, rt_now;
pa_assert(tv);
pa_gettimeofday(&wc_now);
pa_rtclock_get(&rt_now);
/* pa_timeval_sub() saturates on underflow! */
if (pa_timeval_cmp(&wc_now, tv) < 0)
pa_timeval_add(&rt_now, pa_timeval_diff(tv, &wc_now));
else
pa_timeval_sub(&rt_now, pa_timeval_diff(&wc_now, tv));
*tv = rt_now;
return tv;
}
#ifdef HAVE_CLOCK_GETTIME
pa_usec_t pa_timespec_load(const struct timespec *ts) {
if (PA_UNLIKELY(!ts))
return PA_USEC_INVALID;
return
(pa_usec_t) ts->tv_sec * PA_USEC_PER_SEC +
(pa_usec_t) ts->tv_nsec / PA_NSEC_PER_USEC;
}
struct timespec* pa_timespec_store(struct timespec *ts, pa_usec_t v) {
pa_assert(ts);
if (PA_UNLIKELY(v == PA_USEC_INVALID)) {
ts->tv_sec = PA_INT_TYPE_MAX(time_t);
ts->tv_nsec = (long) (PA_NSEC_PER_SEC-1);
return NULL;
}
ts->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
ts->tv_nsec = (long) ((v % PA_USEC_PER_SEC) * PA_NSEC_PER_USEC);
return ts;
}
#endif
static struct timeval* wallclock_from_rtclock(struct timeval *tv) {
struct timeval wc_now, rt_now;
pa_assert(tv);
pa_gettimeofday(&wc_now);
pa_rtclock_get(&rt_now);
/* pa_timeval_sub() saturates on underflow! */
if (pa_timeval_cmp(&rt_now, tv) < 0)
pa_timeval_add(&wc_now, pa_timeval_diff(tv, &rt_now));
else
pa_timeval_sub(&wc_now, pa_timeval_diff(&rt_now, tv));
*tv = wc_now;
return tv;
}
struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, bool rtclock) {
pa_assert(tv);
if (v == PA_USEC_INVALID)
return NULL;
pa_timeval_store(tv, v);
if (rtclock)
tv->tv_usec |= PA_TIMEVAL_RTCLOCK;
else
wallclock_from_rtclock(tv);
return tv;
}