support: Handle supported clocks with timerfd

We don't need to follow a clock when it is one of the supported clocks
for timerfd.
This commit is contained in:
Wim Taymans 2023-02-01 16:19:14 +01:00
parent e3b358ac8b
commit 206df03c27

View file

@ -87,6 +87,8 @@ struct impl {
bool started; bool started;
bool following; bool following;
bool tracking;
clockid_t timer_clockid;
uint64_t next_time; uint64_t next_time;
uint64_t last_time; uint64_t last_time;
uint64_t base_time; uint64_t base_time;
@ -112,6 +114,13 @@ static const struct clock_info {
{ "boottime", CLOCK_BOOTTIME }, { "boottime", CLOCK_BOOTTIME },
}; };
static bool clock_for_timerfd(clockid_t id)
{
return id == CLOCK_REALTIME ||
id == CLOCK_MONOTONIC ||
id == CLOCK_BOOTTIME;
}
static clockid_t clock_name_to_id(const char *name) static clockid_t clock_name_to_id(const char *name)
{ {
SPA_FOR_EACH_ELEMENT_VAR(clock_info, i) { SPA_FOR_EACH_ELEMENT_VAR(clock_info, i) {
@ -152,7 +161,7 @@ static inline uint64_t gettime_nsec(struct impl *this, clockid_t clock_id)
static int set_timers(struct impl *this) static int set_timers(struct impl *this)
{ {
this->next_time = gettime_nsec(this, CLOCK_MONOTONIC); this->next_time = gettime_nsec(this, this->timer_clockid);
spa_log_debug(this->log, "%p now:%"PRIu64, this, this->next_time); spa_log_debug(this->log, "%p now:%"PRIu64, this, this->next_time);
@ -245,7 +254,6 @@ static void on_timeout(struct spa_source *source)
uint32_t rate; uint32_t rate;
double corr = 1.0, err = 0.0; double corr = 1.0, err = 0.0;
int res; int res;
bool following;
if ((res = spa_system_timerfd_read(this->data_system, if ((res = spa_system_timerfd_read(this->data_system,
this->timer_source.fd, &expirations)) < 0) { this->timer_source.fd, &expirations)) < 0) {
@ -261,11 +269,9 @@ static void on_timeout(struct spa_source *source)
duration = 1024; duration = 1024;
rate = 48000; rate = 48000;
} }
following = (this->props.clock_id != CLOCK_MONOTONIC);
nsec = this->next_time; nsec = this->next_time;
if (following) if (this->tracking)
/* we are actually following another clock */ /* we are actually following another clock */
current_time = gettime_nsec(this, this->props.clock_id); current_time = gettime_nsec(this, this->props.clock_id);
else else
@ -296,7 +302,7 @@ static void on_timeout(struct spa_source *source)
position += duration; position += duration;
this->last_time = current_time; this->last_time = current_time;
if (following) { if (this->tracking) {
corr = spa_dll_update(&this->dll, err); corr = spa_dll_update(&this->dll, err);
this->next_time = nsec + duration / corr * 1e9 / rate; this->next_time = nsec + duration / corr * 1e9 / rate;
} else { } else {
@ -306,7 +312,7 @@ static void on_timeout(struct spa_source *source)
if (SPA_UNLIKELY((this->next_time - this->base_time) > BW_PERIOD)) { if (SPA_UNLIKELY((this->next_time - this->base_time) > BW_PERIOD)) {
this->base_time = this->next_time; this->base_time = this->next_time;
spa_log_info(this->log, "%p: rate:%f " spa_log_debug(this->log, "%p: rate:%f "
"bw:%f dur:%"PRIu64" max:%f drift:%f", "bw:%f dur:%"PRIu64" max:%f drift:%f",
this, corr, this->dll.bw, duration, this, corr, this->dll.bw, duration,
this->max_error, err); this->max_error, err);
@ -429,7 +435,7 @@ static int impl_node_process(void *object)
spa_log_trace(this->log, "process %d", this->props.freewheel); spa_log_trace(this->log, "process %d", this->props.freewheel);
if (this->props.freewheel) { if (this->props.freewheel) {
this->next_time = gettime_nsec(this, CLOCK_MONOTONIC); this->next_time = gettime_nsec(this, this->timer_clockid);
set_timeout(this, this->next_time); set_timeout(this, this->next_time);
} }
return SPA_STATUS_HAVE_DATA | SPA_STATUS_NEED_DATA; return SPA_STATUS_HAVE_DATA | SPA_STATUS_NEED_DATA;
@ -574,12 +580,14 @@ impl_init(const struct spa_handle_factory *factory,
clock_id_to_name(this->props.clock_id)); clock_id_to_name(this->props.clock_id));
} }
this->tracking = !clock_for_timerfd(this->props.clock_id);
this->timer_clockid = this->tracking ? CLOCK_MONOTONIC : this->props.clock_id;
this->max_error = 128; this->max_error = 128;
this->timer_source.func = on_timeout; this->timer_source.func = on_timeout;
this->timer_source.data = this; this->timer_source.data = this;
this->timer_source.fd = spa_system_timerfd_create(this->data_system, this->timer_source.fd = spa_system_timerfd_create(this->data_system,
CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); this->timer_clockid, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK);
this->timer_source.mask = SPA_IO_IN; this->timer_source.mask = SPA_IO_IN;
this->timer_source.rmask = 0; this->timer_source.rmask = 0;