src/settings.c \
src/htsbuf.c \
src/trap.c \
- src/avg.c \
src/htsstr.c \
src/tvhpoll.c \
src/huffman.c \
at->at_access = access_copy(a);
TAILQ_INSERT_TAIL(&access_tickets, at, at_link);
- gtimer_arm(&at->at_timer, access_ticket_timout, at, 60*5);
+ mtimer_arm_rel(&at->at_timer, access_ticket_timout, at, 60*5);
return at->at_id;
}
if((at = access_ticket_find(id)) == NULL)
return -1;
- gtimer_disarm(&at->at_timer);
+ mtimer_disarm(&at->at_timer);
access_ticket_destroy(at);
return 0;
TAILQ_ENTRY(access_ticket) at_link;
- gtimer_t at_timer;
+ mtimer_t at_timer;
char *at_resource;
access_t *at_access;
} access_ticket_t;
+++ /dev/null
-/*
- * Averaging functions
- * Copyright (C) 2007 Andreas Öman
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "avg.h"
-#include <stdlib.h>
-
-void
-avgstat_init(avgstat_t *as, int depth)
-{
- TAILQ_INIT(&as->as_queue);
- pthread_mutex_init(&as->as_mutex, NULL);
- as->as_depth = depth;
-}
-
-
-void
-avgstat_flush(avgstat_t *as)
-{
- avgstat_entry_t *ase;
-
- while((ase = TAILQ_FIRST(&as->as_queue)) != NULL) {
- TAILQ_REMOVE(&as->as_queue, ase, ase_link);
- free(ase);
- }
-}
-
-
-static void
-avgstat_expire(avgstat_t *as, int now)
-{
- avgstat_entry_t *ase;
-
- while(1) {
- ase = TAILQ_LAST(&as->as_queue, avgstat_entry_queue);
- if(ase == NULL || ase->ase_clock > now - as->as_depth)
- break;
- TAILQ_REMOVE(&as->as_queue, ase, ase_link);
- free(ase);
- }
-}
-
-
-void
-avgstat_add(avgstat_t *as, int count, time_t now)
-{
- avgstat_entry_t *ase;
-
- pthread_mutex_lock(&as->as_mutex);
- ase = TAILQ_FIRST(&as->as_queue);
- if(ase != NULL && ase->ase_clock == now) {
- ase->ase_count += count;
- } else {
- ase = malloc(sizeof(avgstat_entry_t));
- TAILQ_INSERT_HEAD(&as->as_queue, ase, ase_link);
- ase->ase_clock = now;
- ase->ase_count = count;
- }
-
- avgstat_expire(as, now);
- pthread_mutex_unlock(&as->as_mutex);
-}
-
-
-unsigned int
-avgstat_read_and_expire(avgstat_t *as, time_t now)
-{
- avgstat_entry_t *ase;
- int r = 0;
-
- pthread_mutex_lock(&as->as_mutex);
-
- avgstat_expire(as, now);
-
- TAILQ_FOREACH(ase, &as->as_queue, ase_link)
- r += ase->ase_count;
-
- pthread_mutex_unlock(&as->as_mutex);
- return r;
-}
-
-unsigned int
-avgstat_read(avgstat_t *as, int depth, time_t now)
-{
- avgstat_entry_t *ase;
- int r = 0;
-
- pthread_mutex_lock(&as->as_mutex);
-
- TAILQ_FOREACH(ase, &as->as_queue, ase_link) {
- if(ase->ase_clock < now - depth)
- break;
- r += ase->ase_count;
- }
- pthread_mutex_unlock(&as->as_mutex);
- return r;
-}
-
+++ /dev/null
-/*
- * Averaging functions
- * Copyright (C) 2007 Andreas Öman
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef AVG_H
-#define AVG_H
-
-#include <pthread.h>
-#include "queue.h"
-
-/*
- * avg stat queue
- */
-
-TAILQ_HEAD(avgstat_entry_queue, avgstat_entry);
-
-typedef struct avgstat {
- pthread_mutex_t as_mutex;
- struct avgstat_entry_queue as_queue;
- int as_depth; /* in seconds */
-} avgstat_t;
-
-typedef struct avgstat_entry {
- TAILQ_ENTRY(avgstat_entry) ase_link;
- int ase_clock;
- int ase_count;
-} avgstat_entry_t;
-
-void avgstat_init(avgstat_t *as, int maxdepth);
-void avgstat_add(avgstat_t *as, int count, time_t now);
-void avgstat_flush(avgstat_t *as);
-unsigned int avgstat_read_and_expire(avgstat_t *as, time_t now);
-unsigned int avgstat_read(avgstat_t *as, int depth, time_t now);
-
-#endif /* AVG_H */
typedef struct bouquet_download {
bouquet_t *bq;
download_t download;
- gtimer_t timer;
+ mtimer_t timer;
} bouquet_download_t;
bouquet_tree_t bouquets;
bouquet_t *bq = bqd->bq;
download_start(&bqd->download, bq->bq_ext_url, bqd);
- gtimer_arm(&bqd->timer, bouquet_download_trigger0, bqd,
- MAX(1, bq->bq_ext_url_period) * 60);
+ mtimer_arm_rel(&bqd->timer, bouquet_download_trigger0, bqd,
+ mono4sec(MAX(1, bq->bq_ext_url_period) * 60));
}
static void
bouquet_download_stop(void *aux)
{
bouquet_download_t *bqd = aux;
- gtimer_disarm(&bqd->timer);
+ mtimer_disarm(&bqd->timer);
}
static int
--- /dev/null
+/*
+ * Tvheadend - structures
+ * Copyright (C) 2007 Andreas Öman
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TVHEADEND_CLOCK_H
+#define TVHEADEND_CLOCK_H
+
+#include <time.h>
+
+#ifndef CLOCK_MONOTONIC_COARSE
+#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
+#endif
+
+#ifdef PLATFORM_DARWIN
+#define CLOCK_MONOTONIC 0
+#define CLOCK_REALTIME 0
+
+static inline int clock_gettime(int clk_id, struct timespec* t) {
+ struct timeval now;
+ int rv = gettimeofday(&now, NULL);
+ if (rv) return rv;
+ t->tv_sec = now.tv_sec;
+ t->tv_nsec = now.tv_usec * 1000;
+ return 0;
+}
+#endif
+
+extern int64_t mdispatch_clock;
+extern time_t gdispatch_clock;
+
+#define MONOCLOCK_RESOLUTION 1000000LL /* microseconds */
+
+static inline int64_t
+mono4sec(int64_t sec)
+{
+ return sec * MONOCLOCK_RESOLUTION;
+}
+
+static inline int64_t
+sec4mono(int64_t monosec)
+{
+ return monosec / MONOCLOCK_RESOLUTION;
+}
+
+static inline int64_t
+mono4ms(int64_t ms)
+{
+ return ms * (MONOCLOCK_RESOLUTION / 1000LL);
+}
+
+static inline int64_t
+ms4mono(int64_t monosec)
+{
+ return monosec / (MONOCLOCK_RESOLUTION / 1000LL);
+}
+
+static inline int64_t
+getmonoclock(void)
+{
+ struct timespec tp;
+
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+
+ return tp.tv_sec * MONOCLOCK_RESOLUTION +
+ (tp.tv_nsec / (1000000000LL/MONOCLOCK_RESOLUTION));
+}
+
+static inline int64_t
+getfastmonoclock(void)
+{
+ struct timespec tp;
+
+ clock_gettime(CLOCK_MONOTONIC_COARSE, &tp);
+
+ return tp.tv_sec * MONOCLOCK_RESOLUTION +
+ (tp.tv_nsec / (1000000000LL/MONOCLOCK_RESOLUTION));
+}
+
+time_t gdispatch_clock_update(void);
+int64_t mdispatch_clock_update(void);
+
+void time_t_out_of_range_notify(int64_t val);
+
+static inline time_t time_t_out_of_range(uint64_t val)
+{
+ time_t r = val;
+ if ((int64_t)r != val) {
+ time_t_out_of_range_notify(val);
+ r = INT32_MAX;
+ }
+ return r;
+}
+
+#endif /* TVHEADEND_CLOCK_H */
uint8_t dr_key_index;
uint8_t dr_key_valid;
uint8_t dr_key_changed;
- uint32_t dr_key_interval;
- time_t dr_key_start;
- time_t dr_key_timestamp[2];
- time_t dr_ecm_start[2];
- time_t dr_ecm_last_key_time;
- time_t dr_last_err;
+ uint64_t dr_key_interval;
+ int64_t dr_key_start;
+ int64_t dr_key_timestamp[2];
+ int64_t dr_ecm_start[2];
+ int64_t dr_ecm_last_key_time;
+ int64_t dr_last_err;
TAILQ_HEAD(, th_descrambler_data) dr_queue;
uint32_t dr_queue_total;
tvhlog_limit_t dr_loglimit_key;
capmt_adapter_t *ca;
capmt_opaque_t *t;
int d, i, j, fatal;
+ int64_t mono;
tvhlog(LOG_INFO, "capmt", "%s active", capmt_name(capmt));
tvhlog(LOG_INFO, "capmt", "%s: Automatic reconnection attempt in in %d seconds", idnode_get_title(&capmt->cac_id, NULL), d);
- tvh_cond_timedwait(&capmt->capmt_cond, &capmt->capmt_mutex,
- getmonoclock() + d * MONOCLOCK_RESOLUTION);
+ mono = mdispatch_clock + mono4sec(d);
+ do {
+ i = tvh_cond_timedwait(&capmt->capmt_cond, &capmt->capmt_mutex, mono);
+ if (i == ETIMEDOUT)
+ break;
+ } while (ERRNO_AGAIN(i));
pthread_mutex_unlock(&capmt->capmt_mutex);
}
char chaninfo[128];
int i;
uint32_t off;
- int64_t delay = (getmonoclock() - es->es_time) / 1000LL; // in ms
+ int64_t delay = (getfastmonoclock() - es->es_time) / 1000LL; // in ms
es->es_pending = 0;
{
cwc_t *cwc = aux;
cwc_message_t *cm;
+ int64_t mono;
int r;
pthread_mutex_lock(&cwc->cwc_writer_mutex);
if((cm = TAILQ_FIRST(&cwc->cwc_writeq)) != NULL) {
TAILQ_REMOVE(&cwc->cwc_writeq, cm, cm_link);
pthread_mutex_unlock(&cwc->cwc_writer_mutex);
- // int64_t ts = getmonoclock();
+ // int64_t ts = getfastmonoclock();
if (tvh_write(cwc->cwc_fd, cm->cm_data, cm->cm_len))
tvhlog(LOG_INFO, "cwc", "write error %s", strerror(errno));
- // printf("Write took %lld usec\n", getmonoclock() - ts);
+ // printf("Write took %lld usec\n", getfastmonoclock() - ts);
free(cm);
pthread_mutex_lock(&cwc->cwc_writer_mutex);
continue;
/* If nothing is to be sent in CWC_KEEPALIVE_INTERVAL seconds we
need to send a keepalive */
- r = tvh_cond_timedwait(&cwc->cwc_writer_cond,
- &cwc->cwc_writer_mutex,
- getmonoclock() + CWC_KEEPALIVE_INTERVAL * MONOCLOCK_RESOLUTION);
- if(r == ETIMEDOUT)
- cwc_send_ka(cwc);
+ mono = mdispatch_clock + mono4sec(CWC_KEEPALIVE_INTERVAL);
+ do {
+ r = tvh_cond_timedwait(&cwc->cwc_writer_cond, &cwc->cwc_writer_mutex, mono);
+ if(r == ETIMEDOUT) {
+ cwc_send_ka(cwc);
+ break;
+ }
+ } while (ERRNO_AGAIN(r));
}
pthread_mutex_unlock(&cwc->cwc_writer_mutex);
cwc_thread(void *aux)
{
cwc_t *cwc = aux;
- int fd, d;
+ int fd, d, r;
char errbuf[100];
char hostname[256];
int port;
int attempts = 0;
+ int64_t mono;
pthread_mutex_lock(&cwc->cwc_mutex);
"%s:%i: Automatic connection attempt in %d seconds",
cwc->cwc_hostname, cwc->cwc_port, d-1);
- tvh_cond_timedwait(&cwc->cwc_cond, &cwc->cwc_mutex,
- getmonoclock() + d * MONOCLOCK_RESOLUTION);
+ mono = mdispatch_clock + mono4sec(d);
+ do {
+ r = tvh_cond_timedwait(&cwc->cwc_cond, &cwc->cwc_mutex, mono);
+ if (r == ETIMEDOUT)
+ break;
+ } while (ERRNO_AGAIN(r));
}
tvhlog(LOG_INFO, "cwc", "%s:%i inactive",
if (pcard->running && cwc->cwc_forward_emm && cwc->cwc_writer_running) {
if (cwc->cwc_emmex) {
if (cwc->cwc_mux != mux) {
- int64_t delta = getmonoclock() - cwc->cwc_update_time;
- if (delta < 25000000UL) /* 25 seconds */
+ if (cwc->cwc_update_time + mono4sec(25) < mdispatch_clock)
goto end_of_job;
}
- cwc->cwc_update_time = getmonoclock();
+ cwc->cwc_update_time = mdispatch_clock;
}
cwc->cwc_mux = mux;
emm_filter(&pcard->cs_ra, data, len, mux, cwc_emm_send, pcard);
tvhlog(LOG_DEBUG, "cwc",
"Sending ECM%s section=%d/%d, for service \"%s\" (seqno: %d)",
chaninfo, section, ep->ep_last_section, t->s_dvb_svcname, es->es_seq);
- es->es_time = getmonoclock();
+ es->es_time = getfastmonoclock();
break;
default:
typedef struct th_descrambler_data {
TAILQ_ENTRY(th_descrambler_data) dd_link;
- time_t dd_timestamp;
+ int64_t dd_timestamp;
sbuf_t dd_sbuf;
} th_descrambler_data_t;
}
static void
-descrambler_data_time_flush(th_descrambler_runtime_t *dr, time_t oldest)
+descrambler_data_time_flush(th_descrambler_runtime_t *dr, int64_t oldest)
{
th_descrambler_data_t *dd;
if (len == 0)
return;
dd = TAILQ_LAST(&dr->dr_queue, th_descrambler_queue);
- if (dd && dd->dd_timestamp == dispatch_clock &&
+ if (dd && sec4mono(dd->dd_timestamp) == sec4mono(mdispatch_clock) &&
(dd->dd_sbuf.sb_data[3] & 0x40) == (tsb[3] & 0x40)) { /* key match */
sbuf_append(&dd->dd_sbuf, tsb, len);
dr->dr_queue_total += len;
return;
}
dd = malloc(sizeof(*dd));
- dd->dd_timestamp = dispatch_clock;
+ dd->dd_timestamp = mdispatch_clock;
sbuf_init(&dd->dd_sbuf);
sbuf_append(&dd->dd_sbuf, tsb, len);
TAILQ_INSERT_TAIL(&dr->dr_queue, dd, dd_link);
dr->dr_service = t;
TAILQ_INIT(&dr->dr_queue);
dr->dr_key_index = 0xff;
- dr->dr_key_interval = 10;
+ dr->dr_key_interval = mono4sec(10);
dr->dr_key_const = constcw;
if (constcw)
tvhtrace("descrambler", "using constcw for \"%s\"", t->s_nicename);
memcpy(dr->dr_key_even, even, dr->dr_csa.csa_keylen);
dr->dr_key_changed |= 1;
dr->dr_key_valid |= 0x40;
- dr->dr_key_timestamp[0] = dispatch_clock;
+ dr->dr_key_timestamp[0] = mdispatch_clock;
}
if (memcmp(empty, odd, dr->dr_csa.csa_keylen)) {
j++;
memcpy(dr->dr_key_odd, odd, dr->dr_csa.csa_keylen);
dr->dr_key_changed |= 2;
dr->dr_key_valid |= 0x80;
- dr->dr_key_timestamp[1] = dispatch_clock;
+ dr->dr_key_timestamp[1] = mdispatch_clock;
}
if (j) {
tvhtrace("descrambler", "Unknown keys from %s for for service \"%s\"",
td->td_nicename, ((mpegts_service_t *)t)->s_dvb_svcname);
}
- dr->dr_ecm_last_key_time = dispatch_clock;
+ dr->dr_ecm_last_key_time = mdispatch_clock;
td->td_keystate = DS_RESOLVED;
td->td_service->s_descrambler = td;
} else {
}
static inline void
-key_update( th_descrambler_runtime_t *dr, uint8_t key, time_t timestamp )
+key_update( th_descrambler_runtime_t *dr, uint8_t key, int64_t timestamp )
{
/* set the even (0) or odd (0x40) key index */
dr->dr_key_index = key & 0x40;
if (dr->dr_key_start) {
- dr->dr_key_interval = dr->dr_key_start + 50 < timestamp ?
- 10 : timestamp - dr->dr_key_start;
+ dr->dr_key_interval = dr->dr_key_start + mono4sec(50) < timestamp ?
+ mono4sec(10) : timestamp - dr->dr_key_start;
dr->dr_key_start = timestamp;
} else {
/* We don't know the exact start key switch time */
- dr->dr_key_start = timestamp - 60;
+ dr->dr_key_start = timestamp - mono4sec(60);
}
}
static inline int
-key_changed ( th_descrambler_runtime_t *dr, uint8_t ki, time_t timestamp )
+key_changed ( th_descrambler_runtime_t *dr, uint8_t ki, int64_t timestamp )
{
return dr->dr_key_index != (ki & 0x40) &&
- dr->dr_key_start + 2 < timestamp;
+ dr->dr_key_start + mono4sec(2) < timestamp;
}
static inline int
}
static inline int
-key_late( th_descrambler_runtime_t *dr, uint8_t ki, time_t timestamp )
+key_late( th_descrambler_runtime_t *dr, uint8_t ki, int64_t timestamp )
{
uint8_t kidx = (ki & 0x40) >> 6;
/* constcw - do not handle keys */
goto late;
}
/* ECM was sent, but no new key was received */
- if (dr->dr_ecm_last_key_time + 2 < dr->dr_key_start &&
+ if (dr->dr_ecm_last_key_time + mono4sec(2) < dr->dr_key_start &&
(!dr->dr_quick_ecm || dr->dr_ecm_start[kidx] + 4 < dr->dr_key_start)) {
late:
dr->dr_key_valid &= ~((ki & 0x40) + 0x40);
key_started( th_descrambler_runtime_t *dr, uint8_t ki )
{
uint8_t kidx = (ki & 0x40) >> 6;
- return (int64_t)dispatch_clock - (int64_t)dr->dr_ecm_start[kidx] < 5;
+ return mdispatch_clock - dr->dr_ecm_start[kidx] < mono4sec(5);
}
static int
/* process the queued TS packets */
if (dr->dr_queue_total > 0) {
- descrambler_data_time_flush(dr, dispatch_clock - (dr->dr_key_interval - 2));
+ descrambler_data_time_flush(dr, mdispatch_clock - (dr->dr_key_interval - mono4sec(2)));
for (dd = TAILQ_FIRST(&dr->dr_queue); dd; dd = dd_next) {
dd_next = TAILQ_NEXT(dd, dd_link);
sb = &dd->dd_sbuf;
"even stream key is not valid");
goto next;
}
- if (key_changed(dr, ki, dispatch_clock)) {
+ if (key_changed(dr, ki, mdispatch_clock)) {
tvhtrace("descrambler", "stream key changed to %s for service \"%s\"",
(ki & 0x40) ? "odd" : "even",
((mpegts_service_t *)t)->s_dvb_svcname);
- if (key_late(dr, ki, dispatch_clock)) {
- tvherror("descrambler", "ECM - key late (%ld seconds) for service \"%s\"",
- dispatch_clock - dr->dr_ecm_last_key_time,
+ if (key_late(dr, ki, mdispatch_clock)) {
+ tvherror("descrambler", "ECM - key late (%ld ms) for service \"%s\"",
+ ms4mono(mdispatch_clock - dr->dr_ecm_last_key_time),
((mpegts_service_t *)t)->s_dvb_svcname);
descrambler_notify_nokey(dr);
if (ecm_reset(t, dr)) {
goto next;
}
}
- key_update(dr, ki, dispatch_clock);
+ key_update(dr, ki, mdispatch_clock);
}
}
dr->dr_skip = 1;
tvhtrace("descrambler", "initial stream key set to %s for service \"%s\"",
(ki & 0x40) ? "odd" : "even",
((mpegts_service_t *)t)->s_dvb_svcname);
- key_update(dr, ki, dispatch_clock);
+ key_update(dr, ki, mdispatch_clock);
break;
} else {
descrambler_data_cut(dr, 188);
}
}
} else if (dr->dr_key_index != (ki & 0x40) &&
- dr->dr_key_start + 2 < dispatch_clock) {
+ dr->dr_key_start + mono4sec(2) < mdispatch_clock) {
tvhtrace("descrambler", "stream key changed to %s for service \"%s\"",
(ki & 0x40) ? "odd" : "even",
((mpegts_service_t *)t)->s_dvb_svcname);
- key_update(dr, ki, dispatch_clock);
+ key_update(dr, ki, mdispatch_clock);
}
}
if (count != failed) {
dbuflen = MAX(300, config.descrambler_buffer);
if (dr->dr_queue_total >= dbuflen * 188) {
descrambler_data_cut(dr, MAX((dbuflen / 10) * 188, len));
- if (dr->dr_last_err + 10 < dispatch_clock) {
- dr->dr_last_err = dispatch_clock;
+ if (dr->dr_last_err + mono4sec(10) < mdispatch_clock) {
+ dr->dr_last_err = mdispatch_clock;
tvherror("descrambler", "cannot decode packets for service \"%s\"",
((mpegts_service_t *)t)->s_dvb_svcname);
} else {
t->s_dvb_svcname);
}
if ((ptr[0] & 0xfe) == 0x80) { /* 0x80 = even, 0x81 = odd */
- dr->dr_ecm_start[ptr[0] & 1] = dispatch_clock;
+ dr->dr_ecm_start[ptr[0] & 1] = mdispatch_clock;
if (dr->dr_quick_ecm)
dr->dr_key_valid &= ~(1 << ((ptr[0] & 1) + 6)); /* 0x40 = even, 0x80 = odd */
}
hc->hc_code, hc->hc_result, hc->hc_data_size);
/* note: http_client_close must be called outside http_client callbacks */
- gtimer_arm(&dn->fetch_timer, download_fetch_done, hc, 0);
+ mtimer_arm_rel(&dn->fetch_timer, download_fetch_done, hc, 0);
out:
pthread_mutex_unlock(&global_lock);
}
}
- gtimer_arm_ms(&dn->pipe_read_timer, download_pipe_read, dn, 250);
+ mtimer_arm_rel(&dn->pipe_read_timer, download_pipe_read, dn, mono4ms(250));
}
/*
int r;
download_pipe_close(dn);
- gtimer_disarm(&dn->pipe_read_timer);
+ mtimer_disarm(&dn->pipe_read_timer);
/* Arguments */
if (spawn_parse_args(&argv, 64, args, NULL)) {
fcntl(dn->pipe_fd, F_SETFL, fcntl(dn->pipe_fd, F_GETFL) | O_NONBLOCK);
- gtimer_arm_ms(&dn->pipe_read_timer, download_pipe_read, dn, 250);
+ mtimer_arm_rel(&dn->pipe_read_timer, download_pipe_read, dn, mono4ms(250));
return 0;
}
dn->url = strdup(url);
}
dn->aux = aux;
- gtimer_arm(&dn->fetch_timer, download_fetch, dn, 0);
+ mtimer_arm_rel(&dn->fetch_timer, download_fetch, dn, 0);
}
/*
dn->http_client = NULL;
}
download_pipe_close(dn);
- gtimer_disarm(&dn->fetch_timer);
- gtimer_disarm(&dn->pipe_read_timer);
+ mtimer_disarm(&dn->fetch_timer);
+ mtimer_disarm(&dn->pipe_read_timer);
free(dn->log); dn->log = NULL;
free(dn->url); dn->url = NULL;
}
void (*stop)(void *aux);
/* internal members */
http_client_t *http_client;
- gtimer_t fetch_timer;
- gtimer_t pipe_read_timer;
+ mtimer_t fetch_timer;
+ mtimer_t pipe_read_timer;
sbuf_t pipe_sbuf;
int pipe_fd;
pid_t pipe_pid;
char *de_channel_name;
gtimer_t de_timer;
- gtimer_t de_deferred_timer;
+ mtimer_t de_deferred_timer;
/**
* These meta fields will stay valid as long as reference count > 0
/**
* Entry change notification timer
*/
- time_t de_last_notify;
+ int64_t de_last_notify;
/**
* Update notification limit
static int dvr_in_init;
#if ENABLE_DBUS_1
-static gtimer_t dvr_dbus_timer;
+static mtimer_t dvr_dbus_timer;
#endif
static void dvr_entry_deferred_destroy(dvr_entry_t *de);
if (de->de_sched_state != DVR_SCHEDULED)
continue;
start = dvr_entry_get_start_time(de, 1);
- if (dispatch_clock < start && start > max)
+ if (gdispatch_clock < start && start > max)
max = start;
}
/* lower the maximum value */
if (de->de_sched_state != DVR_SCHEDULED)
continue;
start = dvr_entry_get_start_time(de, 1);
- if (dispatch_clock < start && start < result)
+ if (gdispatch_clock < start && start < result)
result = start;
}
/* different? send it.... */
dvr_entry_retention_arm(dvr_entry_t *de, gti_callback_t *cb, time_t when)
{
uint32_t rerecord = dvr_entry_get_rerecord_errors(de);
- if (rerecord && (when - dispatch_clock) > 3600) {
- when = dispatch_clock + 3600;
+ if (rerecord && (when - gdispatch_clock) > 3600) {
+ when = gdispatch_clock + 3600;
cb = dvr_timer_rerecord;
}
- gtimer_arm_abs(&de->de_timer, cb, de, when);
+ gtimer_arm_absn(&de->de_timer, cb, de, when);
}
/*
stop = time_t_out_of_range((int64_t)de->de_stop + removal * (int64_t)86400);
if ((removal > 0 || retention == 0) && removal < DVR_RET_SPACE) {
- if (stop > dispatch_clock) {
+ if (stop > gdispatch_clock) {
dvr_entry_retention_arm(de, dvr_timer_remove_files, stop);
return;
}
/* EPG thinks that the program is running */
if(de->de_running_start > de->de_running_stop && !de->de_dont_reschedule) {
- stop = dispatch_clock + 10;
+ stop = gdispatch_clock + 10;
if (de->de_sched_state == DVR_RECORDING)
goto recording;
}
} else if (de->de_sched_state == DVR_RECORDING) {
recording:
- gtimer_arm_abs(&de->de_timer, dvr_timer_stop_recording, de, stop);
+ gtimer_arm_absn(&de->de_timer, dvr_timer_stop_recording, de, stop);
} else if (de->de_channel && de->de_channel->ch_enabled) {
dvr_entry_set_state(de, DVR_SCHEDULED, DVR_RS_PENDING, de->de_last_error);
tvhtrace("dvr", "entry timer scheduled for %"PRItime_t, start);
- gtimer_arm_abs(&de->de_timer, dvr_timer_start_recording, de, start);
+ gtimer_arm_absn(&de->de_timer, dvr_timer_start_recording, de, start);
#if ENABLE_DBUS_1
- gtimer_arm(&dvr_dbus_timer, dvr_dbus_timer_cb, NULL, 5);
+ mtimer_arm_rel(&dvr_dbus_timer, dvr_dbus_timer_cb, NULL, mono4sec(5));
#endif
} else {
if(de->de_sched_state == DVR_RECORDING) {
dvr_stop_recording(de, SM_CODE_SOURCE_RECONFIGURED, 1, 1);
dvr_rec_migrate(de, n);
- n->de_start = dispatch_clock;
+ n->de_start = gdispatch_clock;
dvr_entry_start_recording(n, 1);
} else {
dvr_entry_set_timer(n);
dvr_entry_warm_time(de);
RB_FOREACH(ev, &de->de_channel->ch_epg_schedule, sched_link) {
if (de->de_bcast == ev) continue;
- if (ev->start - pre < dispatch_clock) continue;
+ if (ev->start - pre < gdispatch_clock) continue;
if (dvr_entry_fuzzy_match(de, ev, 0, INT64_MAX))
if (!e || e->start > ev->start)
e = ev;
#endif
gtimer_disarm(&de->de_timer);
- gtimer_disarm(&de->de_deferred_timer);
+ mtimer_disarm(&de->de_deferred_timer);
#if ENABLE_DBUS_1
- gtimer_arm(&dvr_dbus_timer, dvr_dbus_timer_cb, NULL, 2);
+ mtimer_arm_rel(&dvr_dbus_timer, dvr_dbus_timer_cb, NULL, mono4sec(2));
#endif
if (de->de_channel)
static void
dvr_entry_deferred_destroy(dvr_entry_t *de)
{
- gtimer_arm(&de->de_deferred_timer, _deferred_destroy_cb, de, 0);
+ mtimer_arm_rel(&de->de_deferred_timer, _deferred_destroy_cb, de, 0);
}
/**
if (!dvr_entry_is_editable(de)) {
if (stop > 0) {
- if (stop < dispatch_clock)
- stop = dispatch_clock;
+ if (stop < gdispatch_clock)
+ stop = gdispatch_clock;
if (stop < de->de_start)
stop = de->de_start;
if (stop != de->de_stop) {
idnode_uuid_as_str(&de->de_id, ubuf),
epg_broadcast_get_title(e, NULL),
channel_get_name(e->channel));
- atomic_exchange_time_t(&de->de_running_start, dispatch_clock);
+ atomic_exchange_time_t(&de->de_running_start, gdispatch_clock);
}
- if (dvr_entry_get_start_time(de, 1) > dispatch_clock) {
- atomic_exchange_time_t(&de->de_start, dispatch_clock);
+ if (dvr_entry_get_start_time(de, 1) > gdispatch_clock) {
+ atomic_exchange_time_t(&de->de_start, gdispatch_clock);
dvr_entry_set_timer(de);
tvhdebug("dvr", "dvr entry %s event %s on %s - EPG start",
idnode_uuid_as_str(&de->de_id, ubuf),
* sometimes, the running bits are parsed randomly for a few moments
* so don't expect that the broacasting has only 5 seconds
*/
- if (de->de_running_start + 5 > dispatch_clock)
+ if (de->de_running_start + 5 > gdispatch_clock)
continue;
srcname = de->de_dvb_eid == e->dvb_eid ? "event" : "other running event";
epg_broadcast_get_title(e, NULL),
channel_get_name(de->de_channel));
}
- atomic_exchange_time_t(&de->de_running_stop, dispatch_clock);
+ atomic_exchange_time_t(&de->de_running_stop, gdispatch_clock);
atomic_exchange_time_t(&de->de_running_pause, 0);
if (de->de_sched_state == DVR_RECORDING && de->de_running_start) {
dvr_stop_recording(de, SM_CODE_OK, 0, 0);
idnode_uuid_as_str(&de->de_id, ubuf),
epg_broadcast_get_title(e, NULL),
channel_get_name(e->channel));
- atomic_exchange_time_t(&de->de_running_pause, dispatch_clock);
+ atomic_exchange_time_t(&de->de_running_pause, gdispatch_clock);
}
}
}
return;
/* EPG thinks that the program is running */
if (de->de_running_start > de->de_running_stop) {
- gtimer_arm(&de->de_timer, dvr_timer_stop_recording, de, 10);
+ gtimer_arm_rel(&de->de_timer, dvr_timer_stop_recording, de, 10);
return;
}
dvr_stop_recording(aux, SM_CODE_OK, 1, 0);
return;
}
- gtimer_arm_abs(&de->de_timer, dvr_timer_stop_recording, de,
- dvr_entry_get_stop_time(de));
+ gtimer_arm_absn(&de->de_timer, dvr_timer_stop_recording, de,
+ dvr_entry_get_stop_time(de));
}
time_t v = *(time_t *)_v;
if (!dvr_entry_is_editable(de)) {
- if (v < dispatch_clock)
- v = dispatch_clock;
+ if (v < gdispatch_clock)
+ v = gdispatch_clock;
}
if (v < de->de_start)
v = de->de_start;
static void
dvr_notify(dvr_entry_t *de)
{
- if (de->de_last_notify + 5 < dispatch_clock) {
+ if (de->de_last_notify + mono4sec(5) < mdispatch_clock) {
idnode_notify_changed(&de->de_id);
- de->de_last_notify = dispatch_clock;
+ de->de_last_notify = mdispatch_clock;
htsp_dvr_entry_update(de);
}
}
streaming_queue_remove(sq, sm);
if (running_disabled) {
- epg_running = real_start <= dispatch_clock;
+ epg_running = real_start <= gdispatch_clock;
} else if (sm->sm_type == SMT_PACKET || sm->sm_type == SMT_MPEGTS) {
running_start = atomic_add_time_t(&de->de_running_start, 0);
running_stop = atomic_add_time_t(&de->de_running_stop, 0);
if (epg_running && atomic_add_time_t(&de->de_running_pause, 0) >= running_start)
epg_running = 2;
} else if (running_stop == 0) {
- if (start_time + 2 >= dispatch_clock) {
+ if (start_time + 2 >= gdispatch_clock) {
TAILQ_INSERT_TAIL(&backlog, sm, sm_link);
continue;
} else {
if (TAILQ_FIRST(&backlog))
streaming_queue_clear(&backlog);
- epg_running = real_start <= dispatch_clock;
+ epg_running = real_start <= gdispatch_clock;
}
} else {
epg_running = 0;
break;
case SMT_START:
- start_time = dispatch_clock;
+ start_time = gdispatch_clock;
packets = 0;
if (ss)
streaming_start_unref(ss);
struct dvr_timerec_entry_queue timerec_entries;
-static gtimer_t dvr_timerec_timer;
+static mtimer_t dvr_timerec_timer;
/**
*
if(dte->dte_channel == NULL)
goto fail;
- limit = dispatch_clock - 600;
- start = dvr_timerec_timecorrection(dispatch_clock, dte->dte_start, &tm_start);
- stop = dvr_timerec_timecorrection(dispatch_clock, dte->dte_stop, &tm_stop);
+ limit = gdispatch_clock - 600;
+ start = dvr_timerec_timecorrection(gdispatch_clock, dte->dte_start, &tm_start);
+ stop = dvr_timerec_timecorrection(gdispatch_clock, dte->dte_stop, &tm_stop);
if (start < limit && stop < limit) {
/* next day */
- start = dvr_timerec_timecorrection(dispatch_clock + 24*60*60,
+ start = dvr_timerec_timecorrection(gdispatch_clock + 24*60*60,
dte->dte_start,
&tm_start);
- stop = dvr_timerec_timecorrection(dispatch_clock + 24*60*60,
+ stop = dvr_timerec_timecorrection(gdispatch_clock + 24*60*60,
dte->dte_stop,
&tm_stop);
}
}
/* load the timer */
- gtimer_arm(&dvr_timerec_timer, dvr_timerec_timer_cb, NULL, 3550);
+ mtimer_arm_rel(&dvr_timerec_timer, dvr_timerec_timer_cb, NULL, mono4sec(3550));
}
void
static int dvr_disk_space_config_idx;
static int dvr_disk_space_config_size;
-static time_t dvr_disk_space_config_lastdelete;
+static int64_t dvr_disk_space_config_lastdelete;
static int64_t dvr_bfree;
static int64_t dvr_btotal;
static int64_t dvr_bused;
static pthread_mutex_t dvr_disk_space_mutex;
-static gtimer_t dvr_disk_space_timer;
+static mtimer_t dvr_disk_space_timer;
static tasklet_t dvr_disk_space_tasklet;
/*
/* When deleting a file from the disk, the system needs some time to actually do this */
/* If calling this function to fast after the previous call, statvfs might be wrong/not updated yet */
/* So we are risking to delete more files than needed, so allow 10s for the system to handle previous deletes */
- if (dvr_disk_space_config_lastdelete + 10 > dispatch_clock) {
+ if (dvr_disk_space_config_lastdelete + mono4sec(10) > mdispatch_clock) {
tvhlog(LOG_WARNING, "dvr","disk space cleanup for config \"%s\" is not allowed now", configName);
return -1;
}
while (availBytes < requiredBytes || ((maximalBytes < usedBytes) && cfg->dvr_cleanup_threshold_used)) {
oldest = NULL;
- stoptime = dispatch_clock;
+ stoptime = gdispatch_clock;
LIST_FOREACH(de, &dvrentries, de_global_link) {
if (de->de_sched_state != DVR_COMPLETED &&
tvhlog(LOG_INFO, "dvr","Delete \"until space needed\" recording \"%s\" with stop time \"%s\" and file size \"%"PRId64" MB\"",
lang_str_get(oldest->de_title, NULL), tbuf, TOMIB(fileSize));
- dvr_disk_space_config_lastdelete = dispatch_clock;
+ dvr_disk_space_config_lastdelete = mdispatch_clock;
if (dvr_entry_get_retention_days(oldest) == DVR_RET_ONREMOVE) {
dvr_entry_delete(oldest); // delete actual file
dvr_entry_destroy(oldest, 1); // also delete database entry
path = strdup(cfg->dvr_storage);
tasklet_arm(&dvr_disk_space_tasklet, dvr_get_disk_space_tcb, path);
}
- gtimer_arm(&dvr_disk_space_timer, dvr_get_disk_space_cb, NULL, 15);
+ mtimer_arm_rel(&dvr_disk_space_timer, dvr_get_disk_space_cb, NULL, mono4sec(15));
}
/**
dvr_config_t *cfg = dvr_config_find_by_name_default(NULL);
pthread_mutex_init(&dvr_disk_space_mutex, NULL);
dvr_get_disk_space_update(cfg->dvr_storage, 1);
- gtimer_arm(&dvr_disk_space_timer, dvr_get_disk_space_cb, NULL, 5);
+ mtimer_arm_rel(&dvr_disk_space_timer, dvr_get_disk_space_cb, NULL, mono4sec(5));
}
/**
dvr_vfs_t *vfs;
tasklet_disarm(&dvr_disk_space_tasklet);
- gtimer_disarm(&dvr_disk_space_timer);
+ mtimer_disarm(&dvr_disk_space_timer);
while ((vfs = LIST_FIRST(&dvrvfs_list)) != NULL) {
LIST_REMOVE(vfs, link);
free(vfs);
eo->update(eo);
LIST_REMOVE(eo, up_link);
eo->_updated = 0;
- eo->created = dispatch_clock;
+ eo->_created = 1;
}
}
tvhtrace("epg", "eo [%p, %u, %d, %s] updated",
eo, eo->id, eo->type, eo->uri);
eo->_updated = 1;
- eo->updated = dispatch_clock;
+ eo->updated = gdispatch_clock;
LIST_INSERT_HEAD(&epg_object_updated, eo, up_link);
}
}
if ((cur = ch->ch_epg_now)) {
if (cur->running != EPG_RUNNING_STOP) {
/* running? don't do anything */
- gtimer_arm(&ch->ch_epg_timer, _epg_channel_timer_callback, ch, 2);
+ gtimer_arm_rel(&ch->ch_epg_timer, _epg_channel_timer_callback, ch, 2);
return;
}
cur->getref(cur);
while ((ebc = RB_FIRST(&ch->ch_epg_schedule))) {
/* Expire */
- if ( ebc->stop <= dispatch_clock ) {
+ if ( ebc->stop <= gdispatch_clock ) {
tvhlog(LOG_DEBUG, "epg", "expire event %u (%s) from %s",
ebc->id, epg_broadcast_get_title(ebc, NULL),
channel_get_name(ch));
continue; // skip to next
/* No now */
- } else if (ebc->start > dispatch_clock) {
+ } else if (ebc->start > gdispatch_clock) {
ch->ch_epg_next = ebc;
next = ebc->start;
if (next) {
tvhlog(LOG_DEBUG, "epg", "arm channel timer @ %"PRItime_t" for %s",
next, channel_get_name(ch));
- gtimer_arm_abs(&ch->ch_epg_timer, _epg_channel_timer_callback, ch, next);
+ gtimer_arm_absn(&ch->ch_epg_timer, _epg_channel_timer_callback, ch, next);
}
/* Remove refs */
epg_broadcast_t *ebc = eo;
char id[16];
- if (ebc->created) {
+ if (ebc->_created) {
htsp_event_delete(ebc);
snprintf(id, sizeof(id), "%u", ebc->id);
notify_delayed(id, "epg", "delete");
else
id[0] = '\0';
- if (ebc->created) {
+ if (ebc->_created) {
htsp_event_update(eo);
notify_delayed(id, "epg", "update");
} else {
epg_broadcast_t **ebc;
if (!channel || !start || !stop) return NULL;
if (stop <= start) return NULL;
- if (stop <= dispatch_clock) return NULL;
+ if (stop <= gdispatch_clock) return NULL;
ebc = _epg_broadcast_skel();
(*ebc)->start = start;
now = ch ? ch->ch_epg_now : NULL;
if (running == EPG_RUNNING_STOP) {
if (now == broadcast && orunning == broadcast->running)
- broadcast->stop = dispatch_clock - 1;
+ broadcast->stop = gdispatch_clock - 1;
} else {
if (broadcast != now && now) {
now->running = EPG_RUNNING_STOP;
if (htsmsg_get_s64(m, "stop", &stop)) return NULL;
if (!start || !stop) return NULL;
if (stop <= start) return NULL;
- if (stop <= dispatch_clock) return NULL;
+ if (stop <= gdispatch_clock) return NULL;
if (!(str = htsmsg_get_str(m, "episode"))) return NULL;
_epg_object_deserialize(m, (epg_object_t*)*skel);
/* Filtering */
if (e == NULL) return;
- if (e->stop < dispatch_clock) return;
+ if (e->stop < gdispatch_clock) return;
if (_eq_comp_num(&eq->start, e->start)) return;
if (_eq_comp_num(&eq->stop, e->stop)) return;
if (eq->duration.comp != EC_NO) {
epg_object_type_t type; ///< Specific object type
uint32_t id; ///< Internal ID
char *uri; ///< Unique ID (from grabber)
- time_t created; ///< Time the object was created
time_t updated; ///< Last time object was changed
- int _updated; ///< Flag to indicate updated
+ uint8_t _updated; ///< Flag to indicate updated
+ uint8_t _created; ///< Flag to indicate creation
int refcount; ///< Reference counting
// Note: could use LIST_ENTRY field to determine this!
sbuf_init_fixed(sb, EPG_DB_ALLOC_STEP);
if (epggrab_conf.epgdb_periodicsave)
- gtimer_arm(&epggrab_save_timer, epg_save_callback, NULL,
- epggrab_conf.epgdb_periodicsave * 3600);
+ gtimer_arm_rel(&epggrab_save_timer, epg_save_callback, NULL,
+ epggrab_conf.epgdb_periodicsave * 3600);
memset(&stats, 0, sizeof(stats));
if ( _epg_write_sect(sb, "config") ) goto error;
}
if (epggrab_conf.epgdb_periodicsave)
- gtimer_arm(&epggrab_save_timer, epg_save_callback, NULL,
- epggrab_conf.epgdb_periodicsave * 3600);
+ gtimer_arm_rel(&epggrab_save_timer, epg_save_callback, NULL,
+ epggrab_conf.epgdb_periodicsave * 3600);
idnode_notify_changed(&epggrab_conf.idnode);
uint8_t om_complete; ///< Has completed a scan
uint8_t om_requeue; ///< Requeue when stolen
uint8_t om_save; ///< something changed
- gtimer_t om_timer; ///< Per mux active timer
- gtimer_t om_data_timer; ///< Any EPG data seen?
+ mtimer_t om_timer; ///< Per mux active timer
+ mtimer_t om_data_timer; ///< Any EPG data seen?
char *om_force_modname;///< Force this module
typedef struct psip_table {
TAILQ_ENTRY(psip_table) pt_link;
mpegts_table_t *pt_table;
- time_t pt_start;
+ int64_t pt_start;
uint16_t pt_pid;
uint16_t pt_type;
uint8_t pt_complete;
mpegts_mux_t *ps_mm;
TAILQ_HEAD(, psip_table) ps_tables;
RB_HEAD(, psip_desc) ps_descs;
- gtimer_t ps_reschedule_timer;
+ mtimer_t ps_reschedule_timer;
uint8_t ps_complete;
uint8_t ps_armed;
} psip_status_t;
free(pd->pd_data);
free(pd);
}
- gtimer_disarm(&st->ps_reschedule_timer);
+ mtimer_disarm(&st->ps_reschedule_timer);
free(st);
} else {
TAILQ_FOREACH(pt, &st->ps_tables, pt_link)
}
ps->ps_refcount++;
mt->mt_destroy = psip_status_destroy;
- pt->pt_start = dispatch_clock;
+ pt->pt_start = mdispatch_clock;
pt->pt_table = mt;
tvhtrace("psip", "table activated - pid 0x%04X type 0x%04X", mt->mt_pid, pt->pt_type);
return mt;
total = 0;
TAILQ_FOREACH(pt, &ps->ps_tables, pt_link) {
total++;
- if (pt->pt_table && pt->pt_start + 10 < dispatch_clock) {
+ if (pt->pt_table && pt->pt_start + mono4sec(10) < mdispatch_clock) {
tvhtrace("psip", "table late: pid = 0x%04X, type = 0x%04X\n", pt->pt_pid, pt->pt_type);
mpegts_table_destroy(pt->pt_table);
pt->pt_table = NULL;
#if 0
for (i = 0; i < total; i++) {
pt = tables[i];
- tvhtrace("psip", "sorted: pid = 0x%04X, type = 0x%04X, time = %"PRItime_t", complete %d\n",
+ tvhtrace("psip", "sorted: pid = 0x%04X, type = 0x%04X, time = %"PRId64", complete %d\n",
pt->pt_pid, pt->pt_type, pt->pt_start, pt->pt_complete);
}
#endif
mpegts_table_destroy(mt);
if (pt)
- gtimer_arm(&ps->ps_reschedule_timer, psip_reschedule_tables_cb, ps, 0);
+ mtimer_arm_rel(&ps->ps_reschedule_timer, psip_reschedule_tables_cb, ps, 0);
if (ps->ps_ota == NULL)
return;
if (ps->ps_complete) {
if (!ps->ps_armed) {
ps->ps_armed = 1;
- gtimer_arm(&ps->ps_reschedule_timer, psip_reschedule_tables_cb, ps, 10);
+ mtimer_arm_rel(&ps->ps_reschedule_timer, psip_reschedule_tables_cb, ps, mono4sec(10));
}
return;
}
HTSMSG_FOREACH(f, tags) {
if (strcmp(f->hmf_name, "broadcast") == 0) {
- ec->laststamp = dispatch_clock;
+ ec->laststamp = gdispatch_clock;
LIST_FOREACH(ilm, &ec->channels, ilm_in1_link) {
ch = (channel_t *)ilm->ilm_in2;
if (!ch->ch_enabled || ch->ch_epg_parent) continue;
(attribs = htsmsg_get_map(subtag, "attrib")) != NULL)
icon = htsmsg_get_str(attribs, "src");
- if(stop <= start || stop <= dispatch_clock) return 0;
+ if(stop <= start || stop <= gdispatch_clock) return 0;
- ec->laststamp = dispatch_clock;
+ ec->laststamp = gdispatch_clock;
LIST_FOREACH(ilm, &ec->channels, ilm_in1_link) {
ch = (channel_t *)ilm->ilm_in2;
if (!ch->ch_enabled || ch->ch_epg_parent) continue;
if((id = htsmsg_get_str(attribs, "id")) == NULL) return 0;
if((tags = htsmsg_get_map(body, "tags")) == NULL) return 0;
if((ch = epggrab_channel_find(mod, id, 1, &save)) == NULL) return 0;
- ch->laststamp = dispatch_clock;
+ ch->laststamp = gdispatch_clock;
stats->channels.total++;
if (save) stats->channels.created++;
epggrab_ota_head_t epggrab_ota_pending;
epggrab_ota_head_t epggrab_ota_active;
-gtimer_t epggrab_ota_kick_timer;
+mtimer_t epggrab_ota_kick_timer;
gtimer_t epggrab_ota_start_timer;
int epggrab_ota_running;
if (TAILQ_EMPTY(&epggrab_ota_pending))
return;
- gtimer_arm(&epggrab_ota_kick_timer, epggrab_ota_kick_cb, NULL, delay);
+ mtimer_arm_rel(&epggrab_ota_kick_timer, epggrab_ota_kick_cb, NULL, mono4sec(delay));
}
static void
mpegts_mux_nice_name(mm, name, sizeof(name));
tvhdebug("epggrab", "grab done for %s (%s)", name, reasons[reason]);
- gtimer_disarm(&om->om_timer);
- gtimer_disarm(&om->om_data_timer);
+ mtimer_disarm(&om->om_timer);
+ mtimer_disarm(&om->om_data_timer);
assert(om->om_q_type == EPGGRAB_OTA_MUX_ACTIVE);
TAILQ_REMOVE(&epggrab_ota_active, om, om_q_link);
TAILQ_INSERT_TAIL(&epggrab_ota_active, om, om_q_link);
om->om_q_type = EPGGRAB_OTA_MUX_ACTIVE;
grace = mpegts_input_grace(mmi->mmi_input, mm);
- gtimer_arm(&om->om_timer, epggrab_ota_timeout_cb, om,
- epggrab_ota_timeout_get() + grace);
- gtimer_arm(&om->om_data_timer, epggrab_ota_data_timeout_cb, om,
- 30 + grace); /* 30 seconds to receive any EPG info */
+ mtimer_arm_rel(&om->om_timer, epggrab_ota_timeout_cb, om,
+ mono4sec(epggrab_ota_timeout_get() + grace));
+ mtimer_arm_rel(&om->om_data_timer, epggrab_ota_data_timeout_cb, om,
+ mono4sec(30 + grace)); /* 30 seconds to receive any EPG info */
if (modname) {
LIST_FOREACH(m, &epggrab_modules, link)
if (!strcmp(m->id, modname)) {
epggrab_ota_next_arm( time_t next )
{
tvhtrace("epggrab", "next ota start event in %li seconds", next - time(NULL));
- gtimer_arm_abs(&epggrab_ota_start_timer, epggrab_ota_start_cb, NULL, next);
+ gtimer_arm_absn(&epggrab_ota_start_timer, epggrab_ota_start_cb, NULL, next);
dbus_emit_signal_s64("/epggrab/ota", "next", next);
}
epggrab_ota_kick(1);
pthread_mutex_lock(&epggrab_ota_mutex);
- if (!cron_multi_next(epggrab_ota_cron_multi, dispatch_clock, &next))
+ if (!cron_multi_next(epggrab_ota_cron_multi, gdispatch_clock, &next))
epggrab_ota_next_arm(next);
else
tvhwarn("epggrab", "ota cron config invalid or unset");
epggrab_ota_map_t *map;
epggrab_ota_svc_link_t *svcl;
- gtimer_disarm(&ota->om_timer);
- gtimer_disarm(&ota->om_data_timer);
+ mtimer_disarm(&ota->om_timer);
+ mtimer_disarm(&ota->om_data_timer);
if (head != NULL)
TAILQ_REMOVE(head, ota, om_q_link);
RB_REMOVE(&epggrab_ota_all, ota, om_global_link);
int64_t htsp_epg_window; // only send async epg updates within this window (seconds)
int64_t htsp_epg_lastupdate; // last update time for async epg events
- gtimer_t htsp_epg_timer; // timer for async epg updates
+ mtimer_t htsp_epg_timer; // timer for async epg updates
/**
* Async mode
th_subscription_t *hs_s; // Temporary
int hs_s_bytes_out;
- gtimer_t hs_s_bytes_out_timer;
+ mtimer_t hs_s_bytes_out_timer;
streaming_target_t hs_input;
profile_chain_t hs_prch;
htsp_msg_q_t hs_q;
- time_t hs_last_report; /* Last queue status report sent */
+ int64_t hs_last_report; /* Last queue status report sent */
int hs_dropstats[PKT_NTYPES];
th_subscription_t *ts = hs->hs_s;
hs->hs_s = NULL;
- gtimer_disarm(&hs->hs_s_bytes_out_timer);
+ mtimer_disarm(&hs->hs_s_bytes_out_timer);
LIST_REMOVE(hs, hs_link);
LIST_INSERT_HEAD(&htsp->htsp_dead_subscriptions, hs, hs_link);
if (htsp->htsp_async_mode & HTSP_ASYNC_EPG) {
/* Only allow to change the window in the correct range */
if (htsp->htsp_epg_window && epgMaxTime > htsp->htsp_epg_lastupdate)
- htsp->htsp_epg_window = epgMaxTime-dispatch_clock;
- } else if (epgMaxTime > dispatch_clock) {
- htsp->htsp_epg_window = epgMaxTime-dispatch_clock;
+ htsp->htsp_epg_window = epgMaxTime-gdispatch_clock;
+ } else if (epgMaxTime > gdispatch_clock) {
+ htsp->htsp_epg_window = epgMaxTime-gdispatch_clock;
} else {
htsp->htsp_epg_window = 0;
}
htsp_subscription_t *hs = aux;
if (hs->hs_s) {
subscription_add_bytes_out(hs->hs_s, atomic_exchange(&hs->hs_s_bytes_out, 0));
- gtimer_arm_ms(&hs->hs_s_bytes_out_timer, _bytes_out_cb, hs, 200);
+ mtimer_arm_rel(&hs->hs_s_bytes_out_timer, _bytes_out_cb, hs, mono4ms(200));
}
}
htsp->htsp_clientname,
NULL);
if (hs->hs_s)
- gtimer_arm_ms(&hs->hs_s_bytes_out_timer, _bytes_out_cb, hs, 200);
+ mtimer_arm_rel(&hs->hs_s_bytes_out_timer, _bytes_out_cb, hs, mono4ms(200));
return NULL;
}
if(htsp.htsp_async_mode)
LIST_REMOVE(&htsp, htsp_async_link);
- gtimer_disarm(&htsp.htsp_epg_timer);
+ mtimer_disarm(&htsp.htsp_epg_timer);
/* deregister this client */
LIST_REMOVE(&htsp, htsp_link);
channel_t *ch;
int64_t maxtime;
- maxtime = dispatch_clock + htsp->htsp_epg_window;
+ maxtime = gdispatch_clock + htsp->htsp_epg_window;
htsp->htsp_epg_lastupdate = maxtime;
/* Push new events */
/* Keep the epg window up to date */
if (htsp->htsp_epg_window)
- gtimer_arm(&htsp->htsp_epg_timer, htsp_epg_window_cb, htsp, HTSP_ASYNC_EPG_INTERVAL);
+ mtimer_arm_rel(&htsp->htsp_epg_timer, htsp_epg_window_cb,
+ htsp, mono4sec(HTSP_ASYNC_EPG_INTERVAL));
}
/**
htsp_send_subscription(htsp, m, pkt->pkt_payload, hs, payloadlen);
atomic_add(&hs->hs_s_bytes_out, payloadlen);
- if(hs->hs_last_report != dispatch_clock) {
+ if(sec4mono(hs->hs_last_report) != sec4mono(mdispatch_clock)) {
/* Send a queue and signal status report every second */
- hs->hs_last_report = dispatch_clock;
+ hs->hs_last_report = mdispatch_clock;
m = htsmsg_create_map();
htsmsg_add_str(m, "method", "queueStatus");
char *hc_data; /* data body */
size_t hc_data_size; /* data body size - result for caller */
- time_t hc_ping_time; /* last issued command */
+ int64_t hc_ping_time; /* last issued command */
char *hc_rbuf; /* read buffer */
size_t hc_rsize; /* read buffer size */
struct http_client_ssl *hc_ssl; /* ssl internals */
- gtimer_t hc_close_timer;
+ mtimer_t hc_close_timer;
/* callbacks */
void (*hc_hdr_create) (http_client_t *hc, http_arg_list_t *h,
empty = TAILQ_EMPTY(&hc->hc_wqueue);
TAILQ_INSERT_TAIL(&hc->hc_wqueue, wcmd, link);
- hc->hc_ping_time = dispatch_clock;
+ hc->hc_ping_time = mdispatch_clock;
if (empty)
return http_client_send_partial(hc);
tvh_cond_t save_cond;
pthread_t save_tid;
static int save_running;
-static gtimer_t save_timer;
+static mtimer_t save_timer;
SKEL_DECLARE(idclasses_skel, idclass_link_t);
return;
ise = malloc(sizeof(*ise));
ise->ise_node = self;
- ise->ise_reqtime = dispatch_clock;
+ ise->ise_reqtime = mdispatch_clock;
if (TAILQ_EMPTY(&idnodes_save) && save_running)
- gtimer_arm(&save_timer, idnode_save_trigger_thread_cb, NULL, IDNODE_SAVE_DELAY);
+ mtimer_arm_rel(&save_timer, idnode_save_trigger_thread_cb, NULL, IDNODE_SAVE_DELAY);
TAILQ_INSERT_TAIL(&idnodes_save, ise, ise_link);
self->in_save = ise;
}
while (save_running) {
if ((ise = TAILQ_FIRST(&idnodes_save)) == NULL ||
- (ise->ise_reqtime + IDNODE_SAVE_DELAY > dispatch_clock)) {
+ (ise->ise_reqtime + IDNODE_SAVE_DELAY > mdispatch_clock)) {
if (ise)
- gtimer_arm(&save_timer, idnode_save_trigger_thread_cb, NULL,
- (ise->ise_reqtime + IDNODE_SAVE_DELAY) - dispatch_clock);
+ mtimer_arm_abs(&save_timer, idnode_save_trigger_thread_cb, NULL,
+ ise->ise_reqtime + IDNODE_SAVE_DELAY);
tvh_cond_wait(&save_cond, &global_lock);
continue;
}
pthread_mutex_lock(&global_lock);
}
- gtimer_disarm(&save_timer);
+ mtimer_disarm(&save_timer);
while ((ise = TAILQ_FIRST(&idnodes_save)) != NULL) {
m = idnode_savefn(ise->ise_node, filename, sizeof(filename));
save_running = 0;
tvh_cond_signal(&save_cond, 0);
pthread_join(save_tid, NULL);
- gtimer_disarm(&save_timer);
+ mtimer_disarm(&save_timer);
while ((il = RB_FIRST(&idclasses)) != NULL) {
RB_REMOVE(&idclasses, il, link);
typedef struct idnode idnode_t;
typedef struct idnode_save idnode_save_t;
-#define IDNODE_SAVE_DELAY 3
+#define IDNODE_SAVE_DELAY (3 * MONOCLOCK_RESOLUTION)
#define SAVEPTR_OUTOFSERVICE ((void *)((intptr_t)-1LL))
struct idnode_save {
TAILQ_ENTRY(idnode_save) ise_link; ///< List chain
idnode_t *ise_node; ///< Node owning this
- time_t ise_reqtime; ///< First request
+ int64_t ise_reqtime; ///< First request
};
/*
static tvh_cond_t imagecache_cond;
static TAILQ_HEAD(, imagecache_image) imagecache_queue;
-static gtimer_t imagecache_timer;
+static mtimer_t imagecache_timer;
#endif
static int
// TODO: this could be more efficient by being targetted, however
// the reality its not necessary and I'd prefer to avoid dumping
// 100's of timers into the global pool
- gtimer_arm(&imagecache_timer, imagecache_timer_cb, NULL, 600);
+ mtimer_arm_rel(&imagecache_timer, imagecache_timer_cb, NULL, mono4sec(600));
#endif
}
imagecache_image_t *img;
#if ENABLE_IMAGECACHE
+ mtimer_disarm(&imagecache_timer);
tvh_cond_signal(&imagecache_cond, 1);
pthread_join(imagecache_tid, NULL);
#endif
imagecache_image_t skel, *i;
char *fn;
int fd = -1;
+ int64_t mono;
lock_assert(&global_lock);
/* Wait */
} else if (i->state == FETCHING) {
- e = tvh_cond_timedwait(&imagecache_cond, &global_lock,
- getmonoclock() + 5 * MONOCLOCK_RESOLUTION);
- if (e == ETIMEDOUT)
- return -1;
+ mono = mdispatch_clock + mono4sec(5);
+ do {
+ e = tvh_cond_timedwait(&imagecache_cond, &global_lock, mono);
+ if (e == ETIMEDOUT)
+ return -1;
+ } while (ERRNO_AGAIN(e));
/* Attempt to fetch */
} else if (i->state == QUEUED) {
*/
mpegts_mux_queue_t mn_scan_pend; // Pending muxes
mpegts_mux_queue_t mn_scan_active; // Active muxes
- gtimer_t mn_scan_timer; // Timer for activity
+ mtimer_t mn_scan_timer; // Timer for activity
/*
* Functions
uint16_t mm_tsid;
int mm_update_pids_flag;
- gtimer_t mm_update_pids_timer;
+ mtimer_t mm_update_pids_timer;
/*
* Services
int mm_scan_weight; ///< Scan priority
int mm_scan_flags; ///< Subscription flags
int mm_scan_init; ///< Flag to timeout handler
- gtimer_t mm_scan_timeout; ///< Timer to handle timeout
+ mtimer_t mm_scan_timeout; ///< Timer to handle timeout
TAILQ_ENTRY(mpegts_mux) mm_scan_link; ///< Link to Queue
mpegts_mux_scan_state_t mm_scan_state; ///< Scanning state
} mm_dmc_origin2;
#endif
void *mm_dmc_origin;
- time_t mm_dmc_origin_expire;
+ int64_t mm_dmc_origin_expire;
char *mm_fastscan_muxes;
sbuf_t s_tsbuf;
time_t s_tsbuf_last;
- /**
- * Average continuity errors
- */
- avgstat_t s_cc_errors;
-
/**
* PCR drift compensation. This should really be per-packet.
*/
/*
* Status
*/
- gtimer_t mi_status_timer;
+ mtimer_t mi_status_timer;
/*
* Input processing
s->s_nicename, s->s_dvb_service_id, s->s_dvb_service_id, where);
service_set_enabled((service_t *)s, 1, SERVICE_AUTO_NORMAL);
}
- s->s_dvb_check_seen = dispatch_clock;
+ s->s_dvb_check_seen = gdispatch_clock;
}
#if ENABLE_MPEGTS_DVB
{
static time_t dvb_last_update = 0;
time_t t;
- if (dvb_last_update + 1800 < dispatch_clock) {
+ if (dvb_last_update + 1800 < gdispatch_clock) {
t = dvb_convert_date(ptr, 0);
if (t > 0) {
tvhtime_update(t, srcname);
- dvb_last_update = dispatch_clock;
+ dvb_last_update = gdispatch_clock;
}
}
}
void
iptv_bouquet_trigger(iptv_network_t *in, int timeout)
{
- gtimer_arm(&in->in_bouquet_timer, iptv_bouquet_update, in, timeout);
+ mtimer_arm_rel(&in->in_bouquet_timer, iptv_bouquet_update, in, mono4sec(timeout));
}
void
pthread_mutex_lock(&iptv_lock);
- gtimer_disarm(&im->im_pause_timer);
+ mtimer_disarm(&im->im_pause_timer);
/* Stop */
if (im->im_handler->stop)
if (limit == UINT32_MAX)
return 0;
limit *= 1000;
- s64 = getmonoclock() - im->im_pcr_start;
+ s64 = getfastmonoclock() - im->im_pcr_start;
im->im_pcr_start += s64;
im->im_pcr += (((s64 / 10LL) * 9LL) + 4LL) / 10LL;
im->im_pcr &= PTS_MASK;
}
pthread_mutex_unlock(&iptv_lock);
if (pause)
- gtimer_arm(&im->im_pause_timer, iptv_input_unpause, im, 1);
+ mtimer_arm_rel(&im->im_pause_timer, iptv_input_unpause, im, mono4sec(1));
}
static void *
if (r == 1) {
pthread_mutex_lock(&global_lock);
if (im->mm_active)
- gtimer_arm(&im->im_pause_timer, iptv_input_unpause, im, 1);
+ mtimer_arm_rel(&im->im_pause_timer, iptv_input_unpause, im, mono4sec(1));
pthread_mutex_unlock(&global_lock);
}
}
s64 = pts_diff(pcr.pcr_first, pcr.pcr_last);
if (s64 != PTS_UNSET) {
im->im_pcr = pcr.pcr_first;
- im->im_pcr_start = getmonoclock();
+ im->im_pcr_start = getfastmonoclock();
im->im_pcr_end = im->im_pcr_start + ((s64 * 100LL) + 50LL) / 9LL;
tvhtrace("iptv-pcr", "pcr: first %"PRId64" last %"PRId64", time start %"PRId64", end %"PRId64,
pcr.pcr_first, pcr.pcr_last, im->im_pcr_start, im->im_pcr_end);
idnode_save_check(&mn->mn_id, delconf);
- gtimer_disarm(&in->in_bouquet_timer);
+ mtimer_disarm(&in->in_bouquet_timer);
if (in->mn_id.in_class == &iptv_auto_network_class)
iptv_auto_network_done(in);
typedef struct auto_private {
iptv_network_t *in_network;
download_t in_download;
- gtimer_t in_auto_timer;
+ mtimer_t in_auto_timer;
} auto_private_t;
/*
iptv_auto_network_stop( void *aux )
{
auto_private_t *ap = aux;
- gtimer_disarm(&ap->in_auto_timer);
+ mtimer_disarm(&ap->in_auto_timer);
}
/*
iptv_network_t *in = ap->in_network;
download_start(&ap->in_download, in->in_url, ap);
- gtimer_arm(&ap->in_auto_timer, iptv_auto_network_trigger0, ap,
- MAX(1, in->in_refetch_period) * 60);
+ mtimer_arm_rel(&ap->in_auto_timer, iptv_auto_network_trigger0, ap,
+ mono4sec(MAX(1, in->in_refetch_period) * 60));
}
/*
{
auto_private_t *ap = in->in_auto;
in->in_auto = NULL;
- gtimer_disarm(&ap->in_auto_timer);
+ mtimer_disarm(&ap->in_auto_timer);
download_done(&ap->in_download);
free(ap);
}
{
iptv_mux_t *im = aux;
file_priv_t *fp = im->im_data;
- struct timespec ts;
ssize_t r;
int fd = fp->fd, pause = 0;
char buf[32*1024];
off_t off = 0;
- int n;
+ int64_t mono;
+ int e;
#if defined(PLATFORM_DARWIN)
fcntl(fd, F_NOCACHE, 1);
pthread_mutex_lock(&iptv_lock);
while (!fp->shutdown && fd > 0) {
while (!fp->shutdown && pause) {
- clock_gettime(CLOCK_REALTIME, &ts);
- ts.tv_sec += 1;
- n = tvh_cond_timedwait(&fp->cond, &iptv_lock,
- getmonoclock() + 1 * MONOCLOCK_RESOLUTION);
- if (n == ETIMEDOUT)
- break;
+ mono = mdispatch_clock + mono4sec(1);
+ do {
+ e = tvh_cond_timedwait(&fp->cond, &iptv_lock, mono);
+ if (e == ETIMEDOUT)
+ break;
+ } while (ERRNO_AGAIN(e));
}
if (fp->shutdown)
break;
htsmsg_t *hls_m3u;
htsmsg_t *hls_key;
uint8_t *hls_si;
- time_t hls_last_si;
+ int64_t hls_last_si;
struct {
char tmp[AES_BLOCK_SIZE];
int tmp_len;
memcpy(hp->hls_si, buf, 2*188);
}
- if (dispatch_clock != hp->hls_last_si && hp->hls_si) {
+ if (hp->hls_last_si + mono4sec(1) <= mdispatch_clock && hp->hls_si) {
/* do rounding to start of the last MPEG-TS packet */
rem = 188 - (hp->off % 188);
if (im->mm_iptv_buffer.sb_ptr >= rem) {
im->mm_iptv_buffer.sb_ptr -= rem;
memcpy(tsbuf, im->mm_iptv_buffer.sb_data + im->mm_iptv_buffer.sb_ptr, rem);
sbuf_append(&im->mm_iptv_buffer, hp->hls_si, 2*188);
- hp->hls_last_si = dispatch_clock;
+ hp->hls_last_si = mdispatch_clock;
sbuf_append(&im->mm_iptv_buffer, tsbuf, rem);
hp->off += rem;
}
if (pause && iptv_http_safe_global_lock(hp)) {
if (im->mm_active && !hp->shutdown)
- gtimer_arm(&im->im_pause_timer, iptv_input_unpause, im, 1);
+ mtimer_arm_rel(&im->im_pause_timer, iptv_input_unpause, im, mono4sec(1));
pthread_mutex_unlock(&global_lock);
}
return 0;
im->mm_iptv_fd = rd;
im->im_data = (void *)(intptr_t)pid;
- im->mm_iptv_respawn_last = dispatch_clock;
+ im->mm_iptv_respawn_last = mdispatch_clock;
if (url)
iptv_input_mux_started(im);
spawn_kill(pid, iptv_pipe_kill_sig(im), im->mm_iptv_kill_timeout);
im->mm_iptv_fd = -1;
im->im_data = NULL;
- if (dispatch_clock < im->mm_iptv_respawn_last + 2) {
+ if (mdispatch_clock < im->mm_iptv_respawn_last + mono4sec(2)) {
tvherror("iptv", "stdin pipe unexpectedly closed: %s",
r < 0 ? strerror(errno) : "No data");
} else {
tvherror("iptv", "unable to respawn %s", im->mm_iptv_url_raw);
} else {
iptv_input_fd_started(im);
- im->mm_iptv_respawn_last = dispatch_clock;
+ im->mm_iptv_respawn_last = mdispatch_clock;
}
}
pthread_mutex_unlock(&iptv_lock);
char *in_url;
char *in_url_sane;
int in_bouquet;
- gtimer_t in_bouquet_timer;
+ mtimer_t in_bouquet_timer;
char *in_ctx_charset;
int64_t in_channel_number;
uint32_t in_refetch_period;
uint32_t mm_iptv_buffer_limit;
iptv_handler_t *im_handler;
- gtimer_t im_pause_timer;
+ mtimer_t im_pause_timer;
int64_t im_pcr;
int64_t im_pcr_start;
udp_multirecv_t um;
char *path;
char *query;
- gtimer_t alive_timer;
+ mtimer_t alive_timer;
int play;
iptv_rtcp_info_t * rtcp_info;
} rtsp_priv_t;
rtsp_priv_t *rp = im->im_data;
rtsp_send(rp->hc, RTSP_CMD_OPTIONS, rp->path, rp->query, NULL);
- gtimer_arm(&rp->alive_timer, iptv_rtsp_alive_cb, im,
- MAX(1, (rp->hc->hc_rtp_timeout / 2) - 1));
+ mtimer_arm_rel(&rp->alive_timer, iptv_rtsp_alive_cb, im,
+ mono4sec(MAX(1, (rp->hc->hc_rtp_timeout / 2) - 1)));
}
/*
/* teardown (or teardown timeout) */
if (hc->hc_cmd == RTSP_CMD_TEARDOWN) {
pthread_mutex_lock(&global_lock);
- gtimer_arm(&hc->hc_close_timer, iptv_rtsp_close_cb, hc, 0);
+ mtimer_arm_rel(&hc->hc_close_timer, iptv_rtsp_close_cb, hc, 0);
pthread_mutex_unlock(&global_lock);
}
return 0;
hc->hc_cmd = HTTP_CMD_NONE;
pthread_mutex_lock(&global_lock);
iptv_input_mux_started(hc->hc_aux);
- gtimer_arm(&rp->alive_timer, iptv_rtsp_alive_cb, im,
- MAX(1, (hc->hc_rtp_timeout / 2) - 1));
+ mtimer_arm_rel(&rp->alive_timer, iptv_rtsp_alive_cb, im,
+ mono4sec(MAX(1, (hc->hc_rtp_timeout / 2) - 1)));
pthread_mutex_unlock(&global_lock);
break;
default:
if (play)
rtsp_teardown(rp->hc, rp->path, "");
pthread_mutex_unlock(&iptv_lock);
- gtimer_disarm(&rp->alive_timer);
+ mtimer_disarm(&rp->alive_timer);
udp_multirecv_free(&rp->um);
if (!play)
http_client_close(rp->hc);
}
- gtimer_arm_ms(&lca->lca_monitor_timer, linuxdvb_ca_monitor, lca, 250);
+ mtimer_arm_rel(&lca->lca_monitor_timer, linuxdvb_ca_monitor, lca, mono4ms(250));
}
linuxdvb_ca_t *
TAILQ_INIT(&lca->lca_capmt_queue);
- gtimer_arm_ms(&lca->lca_monitor_timer, linuxdvb_ca_monitor, lca, 250);
+ mtimer_arm_rel(&lca->lca_monitor_timer, linuxdvb_ca_monitor, lca, mono4ms(250));
return lca;
}
free(lcc);
if (!TAILQ_EMPTY(&lca->lca_capmt_queue)) {
- gtimer_arm_ms(&lca->lca_capmt_queue_timer,
- linuxdvb_ca_process_capmt_queue, lca, i);
+ mtimer_arm_rel(&lca->lca_capmt_queue_timer,
+ linuxdvb_ca_process_capmt_queue, lca, mono4ms(i));
}
}
ca_pmt_list_mgmt2str(lcc->list_mgmt));
}
- gtimer_arm_ms(&lca->lca_capmt_queue_timer,
- linuxdvb_ca_process_capmt_queue, lca, 50);
+ mtimer_arm_rel(&lca->lca_capmt_queue_timer,
+ linuxdvb_ca_process_capmt_queue, lca, mono4ms(50));
}
void linuxdvb_ca_save( linuxdvb_ca_t *lca, htsmsg_t *msg )
if (lfe->lfe_satconf)
linuxdvb_satconf_reset(lfe->lfe_satconf);
}
- gtimer_disarm(&lfe->lfe_monitor_timer);
+ mtimer_disarm(&lfe->lfe_monitor_timer);
/* Ensure FE opened (if not powersave) */
} else if (!lfe->lfe_powersave && lfe->lfe_fe_fd <= 0 && lfe->lfe_fe_path) {
lfe->lfe_status2 = 0;
/* Ensure it won't happen immediately */
- gtimer_arm(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 2);
+ mtimer_arm_rel(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, mono4sec(2));
if (lfe->lfe_satconf && lfe->lfe_refcount == 1)
linuxdvb_satconf_post_stop_mux(lfe->lfe_satconf);
lfe2->lfe_status = 0;
lfe2->lfe_status2 = 0;
/* Ensure it won't happen immediately */
- gtimer_arm(&lfe2->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 2);
+ mtimer_arm_rel(&lfe2->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, mono4sec(2));
if (lfe2->lfe_satconf)
linuxdvb_satconf_post_stop_mux(lfe2->lfe_satconf);
lfe2->lfe_in_setup = 0;
signal_status_t sigstat;
streaming_message_t sm;
service_t *s;
- int logit = 0, retune;
+ int logit = 0, retune, e;
uint32_t period = MINMAX(lfe->lfe_status_period, 250, 8000);
#if DVB_VER_ATLEAST(5,10)
struct dtv_property fe_properties[6];
if (!mmi || !lfe->lfe_ready) return;
/* re-arm */
- gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, period);
+ mtimer_arm_rel(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, mono4ms(period));
/* Get current status */
if (ioctl(lfe->lfe_fe_fd, FE_READ_STATUS, &fe_status) == -1) {
if (lfe->lfe_locked && lfe->lfe_freq > 0) {
tvhlog(LOG_WARNING, "linuxdvb", "%s - %s", buf, retune ? "retune" : "retune nodata");
linuxdvb_frontend_tune0(lfe, mmi, lfe->lfe_freq);
- gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 50);
+ mtimer_arm_rel(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, mono4ms(50));
lfe->lfe_locked = 1;
}
}
pthread_mutex_lock(&lfe->lfe_dvr_lock);
tvhthread_create(&lfe->lfe_dvr_thread, NULL,
linuxdvb_frontend_input_thread, lfe, "lnxdvb-front");
- tvh_cond_wait(&lfe->lfe_dvr_cond, &lfe->lfe_dvr_lock);
+ do {
+ e = tvh_cond_wait(&lfe->lfe_dvr_cond, &lfe->lfe_dvr_lock);
+ if (e == ETIMEDOUT)
+ break;
+ } while (ERRNO_AGAIN(e));
pthread_mutex_unlock(&lfe->lfe_dvr_lock);
/* Table handlers */
/* Re-arm (quick) */
} else {
- gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor,
- lfe, 50);
+ mtimer_arm_rel(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor,
+ lfe, mono4ms(50));
/* Monitor 1 per sec */
- if (dispatch_clock < lfe->lfe_monitor)
+ if (mdispatch_clock < lfe->lfe_monitor)
return;
- lfe->lfe_monitor = dispatch_clock + 1;
+ lfe->lfe_monitor = mdispatch_clock + mono4sec(1);
}
} else {
- if (dispatch_clock < lfe->lfe_monitor)
+ if (mdispatch_clock < lfe->lfe_monitor)
return;
- lfe->lfe_monitor = dispatch_clock + (period + 999) / 1000;
+ lfe->lfe_monitor = mdispatch_clock + mono4sec((period + 999) / 1000);
}
/* Statistics - New API */
if (!r) {
time(&lfe->lfe_monitor);
lfe->lfe_monitor += 4;
- gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 50);
+ mtimer_arm_rel(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, mono4ms(50));
lfe->lfe_ready = 1;
}
mpegts_input_stop_all((mpegts_input_t*)lfe);
/* Stop monitor */
- gtimer_disarm(&lfe->lfe_monitor_timer);
+ mtimer_disarm(&lfe->lfe_monitor_timer);
/* Close FDs */
if (lfe->lfe_fe_fd > 0)
int lfe_nodata;
int lfe_freq;
time_t lfe_monitor;
- gtimer_t lfe_monitor_timer;
+ mtimer_t lfe_monitor_timer;
tvhlog_limit_t lfe_status_log;
/*
int lca_enabled;
int lca_high_bitrate_mode;
int lca_capmt_query;
- gtimer_t lca_monitor_timer;
- gtimer_t lca_capmt_queue_timer;
+ mtimer_t lca_monitor_timer;
+ mtimer_t lca_capmt_queue_timer;
int lca_capmt_interval;
int lca_capmt_query_interval;
pthread_t lca_en50221_thread;
/*
* Diseqc handling
*/
- gtimer_t ls_diseqc_timer;
+ mtimer_t ls_diseqc_timer;
int ls_diseqc_idx;
int ls_diseqc_repeats;
int ls_diseqc_full;
( linuxdvb_satconf_t *ls )
{
ls->ls_mmi = NULL;
- gtimer_disarm(&ls->ls_diseqc_timer);
+ mtimer_disarm(&ls->ls_diseqc_timer);
if (ls->ls_frontend && ls->ls_lnb_poweroff) {
linuxdvb_diseqc_set_volt(ls, -1);
linuxdvb_satconf_reset(ls);
/* Pending */
if (r != 0) {
tvhtrace("diseqc", "waiting %d seconds to finish setup for %s", r, lds[i]->ld_type);
- gtimer_arm(&ls->ls_diseqc_timer, linuxdvb_satconf_ele_tune_cb, lse, r);
+ mtimer_arm_rel(&ls->ls_diseqc_timer, linuxdvb_satconf_ele_tune_cb, lse, mono4sec(r));
ls->ls_diseqc_idx = i + 1;
return 0;
}
char ubuf[UUID_HEX_SIZE];
if (delconf)
hts_settings_remove("input/linuxdvb/satconfs/%s", idnode_uuid_as_str(&ls->ls_id, ubuf));
- gtimer_disarm(&ls->ls_diseqc_timer);
+ mtimer_disarm(&ls->ls_diseqc_timer);
for (lse = TAILQ_FIRST(&ls->ls_elements); lse != NULL; lse = nxt) {
nxt = TAILQ_NEXT(lse, lse_link);
linuxdvb_satconf_ele_destroy(lse);
/* Arm timer */
if (LIST_FIRST(&mi->mi_mux_active) == NULL)
- gtimer_arm(&mi->mi_status_timer, mpegts_input_status_timer,
- mi, 1);
+ mtimer_arm_rel(&mi->mi_status_timer, mpegts_input_status_timer, mi, mono4sec(1));
/* Update */
mmi->mmi_mux->mm_active = mmi;
/* Disarm timer */
if (LIST_FIRST(&mi->mi_mux_active) == NULL)
- gtimer_disarm(&mi->mi_status_timer);
+ mtimer_disarm(&mi->mi_status_timer);
mi->mi_display_name(mi, buf, sizeof(buf));
tvhtrace("mpegts", "%s - flush subscribers", buf);
if (len < (MIN_TS_PKT * 188) && (flags & MPEGTS_DATA_CC_RESTART) == 0) {
/* For slow streams, check also against the clock */
- if (dispatch_clock == mi->mi_last_dispatch)
+ if (sec4mono(mdispatch_clock) == sec4mono(mi->mi_last_dispatch))
return;
}
- mi->mi_last_dispatch = dispatch_clock;
+ mi->mi_last_dispatch = mdispatch_clock;
/* Check for sync */
while ( (len >= MIN_TS_SYN) &&
tvh_input_stream_destroy(&st);
}
pthread_mutex_unlock(&mi->mi_output_lock);
- gtimer_arm(&mi->mi_status_timer, mpegts_input_status_timer, mi, 1);
+ mtimer_arm_rel(&mi->mi_status_timer, mpegts_input_status_timer, mi, mono4sec(1));
mpegts_input_dbus_notify(mi, subs);
}
t = mpegts_input_grace(mi, mm);
/* Setup timeout */
- gtimer_arm(&mm->mm_scan_timeout, mpegts_mux_scan_timeout, mm, t);
+ mtimer_arm_rel(&mm->mm_scan_timeout, mpegts_mux_scan_timeout, mm, mono4sec(t));
}
}
}
/* Stop PID timer */
- gtimer_disarm(&mm->mm_update_pids_timer);
+ mtimer_disarm(&mm->mm_update_pids_timer);
/* Free memory */
idnode_save_check(&mm->mm_id, 1);
mpegts_mux_update_pids ( mpegts_mux_t *mm )
{
if (mm && mm->mm_active)
- gtimer_arm(&mm->mm_update_pids_timer, mpegts_mux_update_pids_cb, mm, 0);
+ mtimer_arm_rel(&mm->mm_update_pids_timer, mpegts_mux_update_pids_cb, mm, 0);
}
void
/* Pending tables (another 20s or 30s - bit arbitrary) */
} else if (q) {
tvhtrace("mpegts", "%s - scan needs more time", buf);
- gtimer_arm(&mm->mm_scan_timeout, mpegts_mux_scan_timeout, mm, w ? 30 : 20);
+ mtimer_arm_rel(&mm->mm_scan_timeout, mpegts_mux_scan_timeout, mm, mono4sec(w ? 30 : 20));
return;
/* Complete */
if (mms->mms_timeout <= 0)
gtimer_disarm(&mms->mms_timer);
else {
- gtimer_arm(&mms->mms_timer, mpegts_mux_sched_timer, mms,
- mms->mms_timeout);
+ gtimer_arm_rel(&mms->mms_timer, mpegts_mux_sched_timer, mms,
+ mms->mms_timeout);
}
} else {
time_t now, nxt;
time(&now);
if (!cron_next(&mms->mms_cronjob, now, &nxt)) {
- gtimer_arm_abs(&mms->mms_timer, mpegts_mux_sched_timer, mms, nxt);
+ gtimer_arm_absn(&mms->mms_timer, mpegts_mux_sched_timer, mms, nxt);
}
}
}
switch (sm->sm_type) {
case SMT_STOP:
- gtimer_arm(&mms->mms_timer, mpegts_mux_sched_timer, mms, 0);
+ gtimer_arm_rel(&mms->mms_timer, mpegts_mux_sched_timer, mms, 0);
break;
default:
// ignore
/* Failed (try-again soon) */
if (!mms->mms_sub) {
- gtimer_arm(&mms->mms_timer, mpegts_mux_sched_timer, mms, 60);
+ gtimer_arm_rel(&mms->mms_timer, mpegts_mux_sched_timer, mms, 60);
/* OK */
} else {
mms->mms_active = 1;
if (mms->mms_timeout > 0) {
- gtimer_arm(&mms->mms_timer, mpegts_mux_sched_timer, mms,
- mms->mms_timeout);
+ gtimer_arm_rel(&mms->mms_timer, mpegts_mux_sched_timer, mms,
+ mms->mms_timeout);
}
}
}
/* Timer */
- gtimer_arm_abs(&mms->mms_timer, mpegts_mux_sched_timer, mms, nxt);
+ gtimer_arm_absn(&mms->mms_timer, mpegts_mux_sched_timer, mms, nxt);
}
}
}
/* Disarm scanning */
- gtimer_disarm(&mn->mn_scan_timer);
+ mtimer_disarm(&mn->mn_scan_timer);
/* Remove from input */
while ((mnl = LIST_FIRST(&mn->mn_inputs)))
/* Initialise scanning */
TAILQ_INIT(&mn->mn_scan_pend);
TAILQ_INIT(&mn->mn_scan_active);
- gtimer_arm(&mn->mn_scan_timer, mpegts_network_scan_timer_cb, mn, 0);
+ mtimer_arm_rel(&mn->mn_scan_timer, mpegts_network_scan_timer_cb, mn, 0);
/* Defaults */
mn->mn_satpos = INT_MAX;
dvb_mux_t *lm = (dvb_mux_t*)mm;
/* the nit tables may be inconsistent (like rolloff ping-pong) */
/* accept information only from one origin mux */
- if (mm->mm_dmc_origin_expire > dispatch_clock && mm->mm_dmc_origin && mm->mm_dmc_origin != origin)
+ if (mm->mm_dmc_origin_expire > mdispatch_clock && mm->mm_dmc_origin && mm->mm_dmc_origin != origin)
goto noop;
#define COMPARE(x, cbit) ({ \
int xr = dmc->x != lm->lm_tuning.x; \
save:
if (mm && save) {
mm->mm_dmc_origin = origin;
- mm->mm_dmc_origin_expire = dispatch_clock + 3600 * 24; /* one day */
+ mm->mm_dmc_origin_expire = mdispatch_clock + mono4sec(3600 * 24); /* one day */
idnode_changed(&mm->mm_id);
}
noop:
/* Re-arm timer. Really this is just a safety measure as we'd normally
* expect the timer to be forcefully triggered on finish of a mux scan
*/
- gtimer_arm(&mn->mn_scan_timer, mpegts_network_scan_timer_cb, mn, 120);
+ mtimer_arm_rel(&mn->mn_scan_timer, mpegts_network_scan_timer_cb, mn, mono4sec(120));
}
/******************************************************************************
TAILQ_REMOVE(&mn->mn_scan_pend, mm, mm_scan_link);
TAILQ_INSERT_SORTED_R(&mn->mn_scan_pend, mpegts_mux_queue,
mm, mm_scan_link, mm_cmp);
- gtimer_arm(&mn->mn_scan_timer, mpegts_network_scan_timer_cb, mn, 10);
+ mtimer_arm_rel(&mn->mn_scan_timer, mpegts_network_scan_timer_cb, mn, mono4sec(10));
weight = 0;
} else {
mpegts_network_scan_queue_del(mm);
tvhdebug("mpegts", "%s - removing mux %s from scan queue", buf2, buf);
mm->mm_scan_state = MM_SCAN_STATE_IDLE;
mm->mm_scan_weight = 0;
- gtimer_disarm(&mm->mm_scan_timeout);
- gtimer_arm(&mn->mn_scan_timer, mpegts_network_scan_timer_cb, mn, 0);
+ mtimer_disarm(&mm->mm_scan_timeout);
+ mtimer_arm_rel(&mn->mn_scan_timer, mpegts_network_scan_timer_cb, mn, 0);
mpegts_network_scan_notify(mm);
}
mm->mm_scan_flags = SUBSCRIPTION_IDLESCAN;
TAILQ_INSERT_SORTED_R(&mn->mn_scan_pend, mpegts_mux_queue,
mm, mm_scan_link, mm_cmp);
- gtimer_arm(&mn->mn_scan_timer, mpegts_network_scan_timer_cb, mn, delay);
+ mtimer_arm_rel(&mn->mn_scan_timer, mpegts_network_scan_timer_cb, mn, mono4sec(delay));
mpegts_network_scan_notify(mm);
}
{
int r;
char buf[256];
+ time_t dispatch_clock = gdispatch_clock;
/* defaults for older version */
s->s_dvb_created = dispatch_clock;
if (sid) s->s_dvb_service_id = sid;
if (pmt_pid) s->s_pmt_pid = pmt_pid;
} else {
- if (s->s_dvb_last_seen > dispatch_clock) /* sanity check */
- s->s_dvb_last_seen = dispatch_clock;
+ if (s->s_dvb_last_seen > gdispatch_clock) /* sanity check */
+ s->s_dvb_last_seen = gdispatch_clock;
}
s->s_dvb_mux = mm;
if ((r = dvb_servicetype_lookup(s->s_dvb_servicetype)) != -1)
if (save) *save = 1;
}
if (create) {
- if ((save && *save) || s->s_dvb_last_seen + 3600 < dispatch_clock) {
- s->s_dvb_last_seen = dispatch_clock;
+ if ((save && *save) || s->s_dvb_last_seen + 3600 < gdispatch_clock) {
+ s->s_dvb_last_seen = gdispatch_clock;
if (save) *save = 1;
}
}
/* Create */
if (create) {
s = mm->mm_network->mn_create_service(mm, sid, pmt_pid);
- s->s_dvb_created = s->s_dvb_last_seen = dispatch_clock;
+ s->s_dvb_created = s->s_dvb_last_seen = gdispatch_clock;
if (save) *save = 1;
}
lock_assert(&global_lock);
- gtimer_disarm(&sd->sd_destroy_timer);
+ mtimer_disarm(&sd->sd_destroy_timer);
idnode_save_check(&sd->th_id, 1);
void
satip_device_destroy_later( satip_device_t *sd, int after )
{
- gtimer_arm_ms(&sd->sd_destroy_timer, satip_device_destroy_cb, sd, after);
+ mtimer_arm_rel(&sd->sd_destroy_timer, satip_device_destroy_cb, sd, mono4ms(after));
}
/*
char *deviceid;
url_t url;
http_client_t *http_client;
- time_t http_start;
+ int64_t http_start;
} satip_discovery_t;
TAILQ_HEAD(satip_discovery_queue, satip_discovery);
static int satip_discoveries_count;
static struct satip_discovery_queue satip_discoveries;
static upnp_service_t *satip_discovery_service;
-static gtimer_t satip_discovery_timer;
-static gtimer_t satip_discovery_static_timer;
-static gtimer_t satip_discovery_timerq;
-static gtimer_t satip_discovery_msearch_timer;
+static mtimer_t satip_discovery_timer;
+static mtimer_t satip_discovery_static_timer;
+static mtimer_t satip_discovery_timerq;
+static mtimer_t satip_discovery_msearch_timer;
static str_list_t *satip_static_clients;
static void
d = next;
next = TAILQ_NEXT(d, disc_link);
if (d->http_client) {
- if (dispatch_clock - d->http_start > 4)
+ if (mdispatch_clock - d->http_start > mono4sec(4))
satip_discovery_destroy(d, 1);
continue;
}
if (d->http_client == NULL)
satip_discovery_destroy(d, 1);
else {
- d->http_start = dispatch_clock;
+ d->http_start = mdispatch_clock;
d->http_client->hc_conn_closed = satip_discovery_http_closed;
http_client_register(d->http_client);
r = http_client_simple(d->http_client, &d->url);
}
}
if (TAILQ_FIRST(&satip_discoveries))
- gtimer_arm(&satip_discovery_timerq, satip_discovery_timerq_cb, NULL, 5);
+ mtimer_arm_rel(&satip_discovery_timerq, satip_discovery_timerq_cb, NULL, mono4sec(5));
}
static void
if (!satip_discovery_find(d) && !satip_device_find(d->uuid)) {
TAILQ_INSERT_TAIL(&satip_discoveries, d, disc_link);
satip_discoveries_count++;
- gtimer_arm_ms(&satip_discovery_timerq, satip_discovery_timerq_cb, NULL, 250);
+ mtimer_arm_rel(&satip_discovery_timerq, satip_discovery_timerq_cb, NULL, mono4ms(250));
i = 0;
}
pthread_mutex_unlock(&global_lock);
/* if new uuid was discovered, retrigger MSEARCH */
pthread_mutex_lock(&global_lock);
if (!satip_device_find(uuid))
- gtimer_arm(&satip_discovery_timer, satip_discovery_timer_cb, NULL, 5);
+ mtimer_arm_rel(&satip_discovery_timer, satip_discovery_timer_cb, NULL, mono4sec(5));
pthread_mutex_unlock(&global_lock);
}
upnp_send(&q, NULL, 0, 0);
htsbuf_queue_flush(&q);
- gtimer_arm_ms(&satip_discovery_msearch_timer, satip_discovery_send_msearch,
- (void *)(intptr_t)(attempt + 1), attempt * 11);
+ mtimer_arm_rel(&satip_discovery_msearch_timer, satip_discovery_send_msearch,
+ (void *)(intptr_t)(attempt + 1), mono4ms(attempt * 11));
#undef MSG
}
return;
for (i = 0; i < satip_static_clients->num; i++)
satip_discovery_static(satip_static_clients->str[i]);
- gtimer_arm(&satip_discovery_static_timer, satip_discovery_static_timer_cb, NULL, 3600);
+ mtimer_arm_rel(&satip_discovery_static_timer, satip_discovery_static_timer_cb, NULL, mono4sec(3600));
}
static void
if (!tvheadend_running)
return;
if (!upnp_running) {
- gtimer_arm(&satip_discovery_timer, satip_discovery_timer_cb, NULL, 1);
+ mtimer_arm_rel(&satip_discovery_timer, satip_discovery_timer_cb,
+ NULL, mono4sec(1));
return;
}
if (satip_discovery_service == NULL) {
}
if (satip_discovery_service)
satip_discovery_send_msearch((void *)1);
- gtimer_arm(&satip_discovery_timer, satip_discovery_timer_cb, NULL, 3600);
+ mtimer_arm_rel(&satip_discovery_timer, satip_discovery_timer_cb,
+ NULL, mono4sec(3600));
}
void
{
if (!satip_enabled)
return;
- gtimer_arm(&satip_discovery_timer, satip_discovery_timer_cb, NULL, 1);
- gtimer_arm(&satip_discovery_static_timer, satip_discovery_static_timer_cb, NULL, 1);
+ mtimer_arm_rel(&satip_discovery_timer, satip_discovery_timer_cb,
+ NULL, mono4sec(1));
+ mtimer_arm_rel(&satip_discovery_static_timer, satip_discovery_static_timer_cb,
+ NULL, mono4sec(1));
}
/*
streaming_pad_deliver(&svc->s_streaming_pad, streaming_msg_clone(&sm));
pthread_mutex_unlock(&svc->s_stream_mutex);
}
- gtimer_arm_ms(&lfe->sf_monitor_timer, satip_frontend_signal_cb, lfe, 250);
+ mtimer_arm_rel(&lfe->sf_monitor_timer, satip_frontend_signal_cb,
+ lfe, mono4ms(250));
}
/* **************************************************************************
mpegts_mux_nice_name(mmi->mmi_mux, buf2, sizeof(buf2));
tvhdebug("satip", "%s - stopping %s", buf1, buf2);
- gtimer_disarm(&lfe->sf_monitor_timer);
+ mtimer_disarm(&lfe->sf_monitor_timer);
/* Stop tune */
tvh_write(lfe->sf_dvr_pipe.wr, "", 1);
/* notify thread that we are ready */
tvh_write(lfe->sf_dvr_pipe.wr, "s", 1);
- gtimer_arm_ms(&lfe->sf_monitor_timer, satip_frontend_signal_cb, lfe, 50);
+ mtimer_arm_rel(&lfe->sf_monitor_timer, satip_frontend_signal_cb,
+ lfe, mono4ms(50));
return 0;
}
}
if (lfe->sf_sbuf.sb_ptr > 64 * 1024 ||
- lfe->sf_last_data_tstamp != dispatch_clock) {
+ lfe->sf_last_data_tstamp + mono4sec(1) <= mdispatch_clock) {
pthread_mutex_lock(&lfe->sf_dvr_lock);
if (lfe->sf_req == lfe->sf_req_thread) {
mmi = lfe->sf_req->sf_mmi;
&lfe->sf_sbuf, 0, NULL);
}
pthread_mutex_unlock(&lfe->sf_dvr_lock);
- lfe->sf_last_data_tstamp = dispatch_clock;
+ lfe->sf_last_data_tstamp = mdispatch_clock;
}
} else if (b[1] == 1) {
lfe->mi_display_name((mpegts_input_t*)lfe, buf, sizeof(buf));
lfe->sf_display_name = buf;
- u64_2 = getmonoclock();
+ u64_2 = getfastmonoclock();
while (!start) {
nfds = tvhpoll_wait(efd, ev, 1, rtsp ? 50 : -1);
if (!tvheadend_running) { exit_flag = 1; goto done; }
- if (rtsp && getmonoclock() - u64_2 > 50000) /* 50ms */
+ if (rtsp && getfastmonoclock() - u64_2 > 50000) /* 50ms */
satip_frontend_close_rtsp(lfe, buf, efd, &rtsp);
if (nfds <= 0) continue;
tc = 1;
while (i) {
- u64_2 = (getmonoclock() - u64) / 1000;
+ u64_2 = (getfastmonoclock() - u64) / 1000;
if (u64_2 >= (uint64_t)i)
break;
r = (uint64_t)i - u64_2;
}
pthread_mutex_lock(&lfe->sf_device->sd_tune_mutex);
- lfe_master->sf_last_tune = getmonoclock();
+ lfe_master->sf_last_tune = getfastmonoclock();
pthread_mutex_unlock(&lfe->sf_device->sd_tune_mutex);
i = 0;
}
/* We need to keep the session alive */
- if (rtsp->hc_ping_time + rtsp->hc_rtp_timeout / 2 < dispatch_clock &&
+ if (rtsp->hc_ping_time + mono4sec(rtsp->hc_rtp_timeout / 2) < mdispatch_clock &&
rtsp->hc_cmd == HTTP_CMD_NONE) {
rtsp_options(rtsp);
reply = 1;
if (lfe->sf_teardown_delay && lfe_master) {
pthread_mutex_lock(&lfe->sf_device->sd_tune_mutex);
- lfe->sf_last_tune = lfe_master->sf_last_tune = getmonoclock();
+ lfe->sf_last_tune = lfe_master->sf_last_tune = getfastmonoclock();
pthread_mutex_unlock(&lfe->sf_device->sd_tune_mutex);
}
}
/* Stop timer */
- gtimer_disarm(&lfe->sf_monitor_timer);
+ mtimer_disarm(&lfe->sf_monitor_timer);
/* Remove from adapter */
TAILQ_REMOVE(&lfe->sf_device->sd_frontends, lfe, sf_link);
{
tvh_hardware_t;
- gtimer_t sd_destroy_timer;
+ mtimer_t sd_destroy_timer;
int sd_inload;
int sd_nosave;
int sf_atsc_c;
int sf_position;
signal_state_t sf_status;
- gtimer_t sf_monitor_timer;
+ mtimer_t sf_monitor_timer;
uint64_t sf_last_tune;
satip_tune_req_t *sf_req;
satip_tune_req_t *sf_req_thread;
cc = tsb2[3] & 0xf;
if(st->es_cc != -1 && cc != st->es_cc) {
/* Let the hardware to stabilize and don't flood the log */
- if (t->s_start_time + 1 < dispatch_clock &&
+ if (t->s_start_time + mono4sec(1) < mdispatch_clock &&
tvhlog_limit(&st->es_cc_log, 10))
tvhwarn("TS", "%s Continuity counter error (total %zi)",
service_component_nicename(st), st->es_cc_log.count);
- avgstat_add(&t->s_cc_errors, 1, dispatch_clock);
- avgstat_add(&st->es_cc_errors, 1, dispatch_clock);
if (!error)
errors++;
error |= 2;
cc = tsb2[3] & 0xf;
if(st->es_cc != -1 && cc != st->es_cc) {
/* Let the hardware to stabilize and don't flood the log */
- if (t->s_start_time + 1 < dispatch_clock &&
+ if (t->s_start_time + mono4sec(1) < mdispatch_clock &&
tvhlog_limit(&st->es_cc_log, 10))
tvhwarn("TS", "%s Continuity counter error (total %zi)",
service_component_nicename(st), st->es_cc_log.count);
- avgstat_add(&t->s_cc_errors, 1, dispatch_clock);
- avgstat_add(&st->es_cc_errors, 1, dispatch_clock);
}
st->es_cc = (cc + 1) & 0xf;
}
if(!error)
service_set_streaming_status_flags((service_t*)t, TSS_INPUT_SERVICE);
- avgstat_add(&t->s_rate, len, dispatch_clock);
-
if(!t->s_scrambled_pass &&
((tsb[3] & 0xc0) ||
(t->s_scrambled_seen && st && st->es_type != SCT_CA))) {
streaming_message_t sm;
pktbuf_t *pb;
- t->s_tsbuf_last = dispatch_clock;
+ t->s_tsbuf_last = mdispatch_clock;
pb = pktbuf_alloc(sb->sb_data, sb->sb_ptr);
pb->pb_err = sb->sb_err;
sbuf_append(sb, src, len);
sb->sb_err += errors;
- if(dispatch_clock == t->s_tsbuf_last && sb->sb_ptr < TS_REMUX_BUFSIZE)
+ if(sec4mono(mdispatch_clock) == sec4mono(t->s_tsbuf_last) &&
+ sb->sb_ptr < TS_REMUX_BUFSIZE)
return;
ts_flush(t, sb);
sb->sb_err += len / 188;
- if(dispatch_clock == t->s_tsbuf_last && sb->sb_err < (TS_REMUX_BUFSIZE / 188))
+ if(sec4mono(mdispatch_clock) == sec4mono(t->s_tsbuf_last) &&
+ sb->sb_err < (TS_REMUX_BUFSIZE / 188))
return;
ts_flush(t, sb);
}
pcr_last = pcr.pcr_first;
#if PLATFORM_LINUX
- pcr_last_realtime = getmonoclock();
+ pcr_last_realtime = getfastmonoclock();
#endif
}
}
if (tvheadend_running) {
brk = tvh_cond_timedwait(&tvhdhomerun_discovery_cond,
&tvhdhomerun_discovery_lock,
- getmonoclock() + 15 * MONOCLOCK_RESOLUTION);
+ mdispatch_clock + mono4sec(15));
brk = !ERRNO_AGAIN(brk) && brk != ETIMEDOUT;
}
pthread_mutex_unlock(&tvhdhomerun_discovery_lock);
lock_assert(&global_lock);
- gtimer_disarm(&hd->hd_destroy_timer);
+ mtimer_disarm(&hd->hd_destroy_timer);
idnode_save_check(&hd->th_id, 1);
streaming_message_t sm;
signal_status_t sigstat;
service_t *svc;
- int res;
+ int res, e;
struct hdhomerun_tuner_status_t tuner_status;
char *tuner_status_str;
if (!mmi || !hfe->hf_ready) return;
/* re-arm */
- gtimer_arm(&hfe->hf_monitor_timer, tvhdhomerun_frontend_monitor_cb, hfe, 1);
+ mtimer_arm_rel(&hfe->hf_monitor_timer, tvhdhomerun_frontend_monitor_cb,
+ hfe, mono4sec(1));
/* Get current status */
pthread_mutex_lock(&hfe->hf_hdhomerun_device_mutex);
tvh_pipe(O_NONBLOCK, &hfe->hf_input_thread_pipe);
pthread_mutex_lock(&hfe->hf_input_thread_mutex);
tvhthread_create(&hfe->hf_input_thread, NULL, tvhdhomerun_frontend_input_thread, hfe, "hdhm-front");
- tvh_cond_wait(&hfe->hf_input_thread_cond, &hfe->hf_input_thread_mutex);
+ do {
+ e = tvh_cond_wait(&hfe->hf_input_thread_cond, &hfe->hf_input_thread_mutex);
+ if (e == ETIMEDOUT)
+ break;
+ } while (ERRNO_AGAIN(e));
pthread_mutex_unlock(&hfe->hf_input_thread_mutex);
/* install table handlers */
((dvb_mux_t *)mm)->lm_tuning.dmc_fe_delsys);
} else { // quick re-arm the timer to wait for signal lock
- gtimer_arm_ms(&hfe->hf_monitor_timer, tvhdhomerun_frontend_monitor_cb, hfe, 50);
+ mtimer_arm_rel(&hfe->hf_monitor_timer, tvhdhomerun_frontend_monitor_cb, hfe, mono4ms(50));
}
}
hfe->hf_status = SIGNAL_NONE;
/* start the monitoring */
- gtimer_arm_ms(&hfe->hf_monitor_timer, tvhdhomerun_frontend_monitor_cb, hfe, 50);
+ mtimer_arm_rel(&hfe->hf_monitor_timer, tvhdhomerun_frontend_monitor_cb, hfe, mono4ms(50));
hfe->hf_ready = 1;
return 0;
hfe->hf_status = 0;
hfe->hf_ready = 0;
- gtimer_arm(&hfe->hf_monitor_timer, tvhdhomerun_frontend_monitor_cb, hfe, 2);
+ mtimer_arm_rel(&hfe->hf_monitor_timer, tvhdhomerun_frontend_monitor_cb, hfe, mono4sec(2));
}
static void tvhdhomerun_frontend_update_pids( mpegts_input_t *mi, mpegts_mux_t *mm )
{
lock_assert(&global_lock);
- gtimer_disarm(&hfe->hf_monitor_timer);
+ mtimer_disarm(&hfe->hf_monitor_timer);
hdhomerun_device_tuner_lockkey_release(hfe->hf_hdhomerun_tuner);
hdhomerun_device_destroy(hfe->hf_hdhomerun_tuner);
{
tvh_hardware_t;
- gtimer_t hd_destroy_timer;
+ mtimer_t hd_destroy_timer;
/*
* Adapter info
uint8_t hf_input_thread_terminating; // Used for terminating the input_thread.
// Global lock for the libhdhomerun library since it seems to have some threading-issues.
- pthread_mutex_t hf_hdhomerun_device_mutex;
+ pthread_mutex_t hf_hdhomerun_device_mutex;
/*
* Reception
*/
char hf_pid_filter_buf[1024];
- gtimer_t hf_monitor_timer;
+ mtimer_t hf_monitor_timer;
mpegts_mux_instance_t *hf_mmi;
/*
* Locals
*/
+static LIST_HEAD(, mtimer) mtimers;
+static tvh_cond_t mtimer_cond;
+static int64_t mtimer_periodic;
+static pthread_t mtimer_tid;
static LIST_HEAD(, gtimer) gtimers;
static pthread_cond_t gtimer_cond;
static TAILQ_HEAD(, tasklet) tasklets;
/**
*
*/
+
+#define safecmp(a, b) ((a) > (b) ? 1 : ((a) < (b) ? -1 : 0))
+
static int
-gtimercmp(gtimer_t *a, gtimer_t *b)
+mtimercmp(mtimer_t *a, mtimer_t *b)
{
- if(a->gti_expire.tv_sec < b->gti_expire.tv_sec)
- return -1;
- if(a->gti_expire.tv_sec > b->gti_expire.tv_sec)
- return 1;
- if(a->gti_expire.tv_nsec < b->gti_expire.tv_nsec)
- return -1;
- if(a->gti_expire.tv_nsec > b->gti_expire.tv_nsec)
- return 1;
- return 0;
+ return safecmp(a->mti_expire, b->mti_expire);
}
/**
*
*/
void
-GTIMER_FCN(gtimer_arm_abs2)
- (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, struct timespec *when)
+GTIMER_FCN(mtimer_arm_abs)
+ (GTIMER_TRACEID_ mtimer_t *mti, mti_callback_t *callback, void *opaque, int64_t when)
{
lock_assert(&global_lock);
- if (gti->gti_callback != NULL)
- LIST_REMOVE(gti, gti_link);
+ if (mti->mti_callback != NULL)
+ LIST_REMOVE(mti, mti_link);
- gti->gti_callback = callback;
- gti->gti_opaque = opaque;
- gti->gti_expire = *when;
+ mti->mti_callback = callback;
+ mti->mti_opaque = opaque;
+ mti->mti_expire = when;
#if ENABLE_GTIMER_CHECK
- gti->gti_id = id;
- gti->gti_fcn = fcn;
+ mti->mti_id = id;
+ mti->mti_fcn = fcn;
#endif
- LIST_INSERT_SORTED(>imers, gti, gti_link, gtimercmp);
+ LIST_INSERT_SORTED(&mtimers, mti, mti_link, mtimercmp);
- if (LIST_FIRST(>imers) == gti)
- pthread_cond_signal(>imer_cond); // force timer re-check
+ if (LIST_FIRST(&mtimers) == mti)
+ tvh_cond_signal(&mtimer_cond, 0); // force timer re-check
}
/**
*
*/
void
-GTIMER_FCN(gtimer_arm_abs)
- (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t when)
+GTIMER_FCN(mtimer_arm_rel)
+ (GTIMER_TRACEID_ mtimer_t *gti, mti_callback_t *callback, void *opaque, int64_t delta)
{
- struct timespec ts;
- ts.tv_nsec = 0;
- ts.tv_sec = when;
#if ENABLE_GTIMER_CHECK
- GTIMER_FCN(gtimer_arm_abs2)(id, fcn, gti, callback, opaque, &ts);
+ GTIMER_FCN(mtimer_arm_abs)(id, fcn, gti, callback, opaque, mdispatch_clock + delta);
#else
- gtimer_arm_abs2(gti, callback, opaque, &ts);
+ mtimer_arm_abs(gti, callback, opaque, mdispatch_clock + delta);
#endif
}
*
*/
void
-GTIMER_FCN(gtimer_arm)
- (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, int delta)
+mtimer_disarm(mtimer_t *mti)
+{
+ if(mti->mti_callback) {
+ LIST_REMOVE(mti, mti_link);
+ mti->mti_callback = NULL;
+ }
+}
+
+/**
+ *
+ */
+static int
+gtimercmp(gtimer_t *a, gtimer_t *b)
+{
+ return safecmp(a->gti_expire, b->gti_expire);
+}
+
+/**
+ *
+ */
+void
+GTIMER_FCN(gtimer_arm_absn)
+ (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t when)
{
+ lock_assert(&global_lock);
+
+ if (gti->gti_callback != NULL)
+ LIST_REMOVE(gti, gti_link);
+
+ gti->gti_callback = callback;
+ gti->gti_opaque = opaque;
+ gti->gti_expire = when;
#if ENABLE_GTIMER_CHECK
- GTIMER_FCN(gtimer_arm_abs)(id, fcn, gti, callback, opaque, dispatch_clock + delta);
-#else
- gtimer_arm_abs(gti, callback, opaque, dispatch_clock + delta);
+ gti->gti_id = id;
+ gti->gti_fcn = fcn;
#endif
+
+ LIST_INSERT_SORTED(>imers, gti, gti_link, gtimercmp);
+
+ if (LIST_FIRST(>imers) == gti)
+ pthread_cond_signal(>imer_cond); // force timer re-check
}
/**
*
*/
void
-GTIMER_FCN(gtimer_arm_ms)
- (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, long delta_ms )
+GTIMER_FCN(gtimer_arm_rel)
+ (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t delta)
{
- struct timespec ts;
- clock_gettime(CLOCK_REALTIME, &ts);
- ts.tv_nsec += (1000000 * delta_ms);
- ts.tv_sec += (ts.tv_nsec / 1000000000);
- ts.tv_nsec %= 1000000000;
#if ENABLE_GTIMER_CHECK
- GTIMER_FCN(gtimer_arm_abs2)(id, fcn, gti, callback, opaque, &ts);
+ GTIMER_FCN(gtimer_arm_absn)(id, fcn, gti, callback, opaque, gdispatch_clock + delta);
#else
- gtimer_arm_abs2(gti, callback, opaque, &ts);
+ gtimer_arm_absn(gti, callback, opaque, gdispatch_clock + delta);
#endif
}
/**
*
*/
-time_t
-dispatch_clock_update(struct timespec *ts)
+int64_t
+mdispatch_clock_update(void)
{
- struct timespec ts1;
- if (ts == NULL)
- ts = &ts1;
- clock_gettime(CLOCK_REALTIME, ts);
-
- /* 1sec stuff */
- if (ts->tv_sec > dispatch_clock) {
- dispatch_clock = ts->tv_sec;
+ int64_t mono = getmonoclock();
+
+ if (mono > mtimer_periodic) {
+ mtimer_periodic = mono + MONOCLOCK_RESOLUTION;
comet_flush(); /* Flush idle comet mailboxes */
}
- return dispatch_clock;
+
+ return mdispatch_clock = mono;
+}
+
+/**
+ *
+ */
+static void *
+mtimer_thread(void *aux)
+{
+ mtimer_t *mti;
+ mti_callback_t *cb;
+ int64_t now, next;
+#if ENABLE_GTIMER_CHECK
+ int64_t mtm;
+ const char *id;
+ const char *fcn;
+#endif
+
+ while (tvheadend_running) {
+ now = mdispatch_clock_update();
+
+ /* Global monoclock timers */
+ pthread_mutex_lock(&global_lock);
+
+ next = now + mono4sec(3600);
+
+ while((mti = LIST_FIRST(&mtimers)) != NULL) {
+
+ if (mti->mti_expire > now) {
+ next = mti->mti_expire;
+ break;
+ }
+
+#if ENABLE_GTIMER_CHECK
+ mtm = getmonoclock();
+ id = mti->mti_id;
+ fcn = mti->mti_fcn;
+#endif
+ cb = mti->mti_callback;
+
+ LIST_REMOVE(mti, mti_link);
+ mti->mti_callback = NULL;
+
+ cb(mti->mti_opaque);
+
+#if ENABLE_GTIMER_CHECK
+ tvhtrace("mtimer", "%s:%s duration %"PRId64"ns", id, fcn, getmonoclock() - mtm);
+#endif
+ }
+
+ /* Periodic updates */
+ if (next > mtimer_periodic)
+ next = mtimer_periodic;
+
+ /* Wait */
+ tvh_cond_timedwait(&mtimer_cond, &global_lock, next);
+ pthread_mutex_unlock(&global_lock);
+ }
+
+ return NULL;
+}
+
+/**
+ *
+ */
+time_t
+gdispatch_clock_update(void)
+{
+ return gdispatch_clock = time(NULL);
}
/**
{
gtimer_t *gti;
gti_callback_t *cb;
+ time_t now;
struct timespec ts;
#if ENABLE_GTIMER_CHECK
int64_t mtm;
const char *fcn;
#endif
- while(tvheadend_running) {
- dispatch_clock_update(&ts);
+ while (tvheadend_running) {
+ now = gdispatch_clock_update();
/* Global timers */
pthread_mutex_lock(&global_lock);
// the top of the list with a 0 offset we could loop indefinitely
#if 0
- tvhdebug("gtimer", "now %ld.%09ld", ts.tv_sec, ts.tv_nsec);
+ tvhdebug("gtimer", "now %"PRItime_t, ts.tv_sec);
LIST_FOREACH(gti, >imers, gti_link)
- tvhdebug("gtimer", " gti %p expire %ld.%08ld",
- gti, gti->gti_expire.tv_sec, gti->gti_expire.tv_nsec);
+ tvhdebug("gtimer", " gti %p expire %"PRItimet, gti, gti->gti_expire.tv_sec);
#endif
+ ts.tv_sec += 3600;
+ ts.tv_nsec = 0;
+
while((gti = LIST_FIRST(>imers)) != NULL) {
- if ((gti->gti_expire.tv_sec > ts.tv_sec) ||
- ((gti->gti_expire.tv_sec == ts.tv_sec) &&
- (gti->gti_expire.tv_nsec > ts.tv_nsec))) {
- ts = gti->gti_expire;
+ if (gti->gti_expire > now) {
+ ts.tv_sec = gti->gti_expire;
break;
}
#endif
}
- /* Bound wait */
- if ((LIST_FIRST(>imers) == NULL) || (ts.tv_sec > (dispatch_clock + 1))) {
- ts.tv_sec = dispatch_clock + 1;
- ts.tv_nsec = 0;
- }
-
/* Wait */
pthread_cond_timedwait(>imer_cond, &global_lock, &ts);
pthread_mutex_unlock(&global_lock);
pthread_mutex_init(&global_lock, NULL);
pthread_mutex_init(&tasklet_lock, NULL);
pthread_mutex_init(&atomic_lock, NULL);
+ tvh_cond_init(&mtimer_cond);
pthread_cond_init(>imer_cond, NULL);
tvh_cond_init(&tasklet_cond);
TAILQ_INIT(&tasklets);
tvheadend_webroot = NULL;
tvheadend_htsp_port = 9982;
tvheadend_htsp_port_extra = 0;
- time(&dispatch_clock);
+ mdispatch_clock = getmonoclock();
+ time(&gdispatch_clock);
/* Command line options */
int opt_help = 0,
/* Initialise clock */
pthread_mutex_lock(&global_lock);
- time(&dispatch_clock);
+ mdispatch_clock = getmonoclock();
+ time(&gdispatch_clock);
/* Signal handling */
sigfillset(&set);
if(opt_abort)
abort();
+ tvhthread_create(&mtimer_tid, NULL, mtimer_thread, NULL, "mtimer");
mainloop();
+ pthread_mutex_lock(&global_lock);
+ tvh_cond_signal(&mtimer_cond, 0);
+ pthread_mutex_unlock(&global_lock);
+ pthread_join(mtimer_tid, NULL);
#if ENABLE_DBUS_1
tvhftrace("main", dbus_server_done);
int64_t cluster_tc;
off_t cluster_pos;
int cluster_maxsize;
- time_t cluster_last_close;
+ int64_t cluster_last_close;
off_t segment_header_pos;
if(mk->cluster != NULL)
mk_write_master(mk, 0x1f43b675, mk->cluster);
mk->cluster = NULL;
- mk->cluster_last_close = dispatch_clock;
+ mk->cluster_last_close = mdispatch_clock;
}
if(vkeyframe && mk->cluster &&
(mk->cluster->hq_size > mk->cluster_maxsize ||
- mk->cluster_last_close + 1 < dispatch_clock))
+ mk->cluster_last_close + mono4sec(1) < mdispatch_clock))
mk_close_cluster(mk);
else if(!mk->has_video && mk->cluster &&
(mk->cluster->hq_size > clusersizemax/40 ||
- mk->cluster_last_close + 1 < dispatch_clock))
+ mk->cluster_last_close + mono4sec(1) < mdispatch_clock))
mk_close_cluster(mk);
else if(mk->cluster && mk->cluster->hq_size > clusersizemax)
h264_sps_t sps[MAX_SPS_COUNT];
h264_pps_t pps[MAX_PPS_COUNT];
- time_t start;
+ int64_t start;
} h264_private_t;
if ((p = st->es_priv) == NULL) {
p = st->es_priv = calloc(1, sizeof(h264_private_t));
- p->start = dispatch_clock;
+ p->start = mdispatch_clock;
}
profile_idc = read_bits(bs, 8);
if((p = st->es_priv) == NULL) {
p = st->es_priv = calloc(1, sizeof(h264_private_t));
- p->start = dispatch_clock;
+ p->start = mdispatch_clock;
}
pps_id = read_golomb_ue(bs);
d = 0;
if (sps->time_scale)
d = 180000 * (uint64_t)sps->units_in_tick / (uint64_t)sps->time_scale;
- if (d == 0 && st->es_frame_duration < 2 && p->start + 4 < dispatch_clock) {
+ if (d == 0 && st->es_frame_duration < 2 && p->start + mono4sec(4) < mdispatch_clock) {
tvhwarn("parser", "H264 stream has not timing information, using 30fps");
d = 3000; /* 90000/30 = 3000 : 30fps */
}
int i;
struct tm tm;
- t = dispatch_clock;
+ t = gdispatch_clock;
localtime_r(&t, &tm);
tm.tm_hour = atoi((char *)buf);
pkt->pkt_aspect_num = st->es_aspect_num;
pkt->pkt_aspect_den = st->es_aspect_den;
- // avgstat_add(&st->es_rate, pkt->pkt_payloadlen, dispatch_clock);
-
/**
* Input is ok
*/
int tf_hasvideo;
int tf_wait_for_video;
int64_t tf_tsref;
- time_t tf_start_time;
+ int64_t tf_start_time;
struct th_pktref_queue tf_ptsq;
struct th_pktref_queue tf_backlog;
streaming_msg_free(sm);
int64_t diff, diff2, threshold;
- if(tfs == NULL || dispatch_clock < tf->tf_start_time) {
+ if(tfs == NULL || mdispatch_clock < tf->tf_start_time) {
pkt_ref_dec(pkt);
return;
}
TAILQ_INIT(&tf->tf_ptsq);
tf->tf_output = output;
- tf->tf_start_time = dispatch_clock;
+ tf->tf_start_time = mdispatch_clock;
streaming_target_init(&tf->tf_input, tsfix_input, tf, 0);
return &tf->tf_input;
}
-/**
- *
- */
-void tsfix_set_start_time(streaming_target_t *pad, time_t start)
-{
- tsfix_t *tf = (tsfix_t *)pad;
-
- tf->tf_start_time = start;
-}
-
-
/**
*
*/
streaming_target_t *tsfix_create(streaming_target_t *output);
-void tsfix_set_start_time(streaming_target_t *pad, time_t start);
-
void tsfix_destroy(streaming_target_t *gh);
satip_rtp_header(satip_rtp_session_t *rtp, struct iovec *v, uint32_t off)
{
uint8_t *data = v->iov_base;
- uint32_t tstamp = dispatch_clock + rtp->seq;
+ uint32_t tstamp = sec4mono(mdispatch_clock) + rtp->seq;
rtp->seq++;
dvb_mux_conf_t dmc;
dvb_mux_conf_t dmc_tuned;
mpegts_apids_t pids;
- gtimer_t timer;
+ mtimer_t timer;
mpegts_mux_t *mux;
int mux_created;
profile_chain_t prch;
{
if (!rs->shutdown_on_close) {
pthread_mutex_lock(&global_lock);
- gtimer_arm(&rs->timer, rtsp_session_timer_cb, rs, RTSP_TIMEOUT);
+ mtimer_arm_rel(&rs->timer, rtsp_session_timer_cb, rs, mono4sec(RTSP_TIMEOUT));
pthread_mutex_unlock(&global_lock);
}
}
static void
rtsp_describe_header(session_t *rs, htsbuf_queue_t *q)
{
- unsigned long mono = getmonoclock();
+ unsigned long mono = mdispatch_clock;
int dvbt, dvbc;
htsbuf_append_str(q, "v=0\r\n");
pthread_mutex_lock(&global_lock);
mpegts_pid_reset(&rs->pids);
rtsp_clean(rs);
- gtimer_disarm(&rs->timer);
+ mtimer_disarm(&rs->timer);
pthread_mutex_unlock(&global_lock);
}
{
TAILQ_REMOVE(&rtsp_sessions, rs, link);
pthread_mutex_lock(&global_lock);
- gtimer_disarm(&rs->timer);
+ mtimer_disarm(&rs->timer);
pthread_mutex_unlock(&global_lock);
mpegts_pid_done(&rs->pids);
free(rs);
struct service_queue service_raw_all;
struct service_queue service_raw_remove;
-static gtimer_t service_raw_remove_timer;
+static mtimer_t service_raw_remove_timer;
static void
service_class_notify_enabled ( void *obj, const char *lang )
if(t->s_status == SERVICE_RUNNING)
stream_clean(es);
- avgstat_flush(&es->es_rate);
- avgstat_flush(&es->es_cc_errors);
-
if (t->s_last_es == es) {
t->s_last_pid = -1;
t->s_last_es = NULL;
{
elementary_stream_t *st;
- gtimer_disarm(&t->s_receive_timer);
+ mtimer_disarm(&t->s_receive_timer);
t->s_stop_feed(t);
t->s_streaming_live = 0;
t->s_scrambled_seen = 0;
t->s_scrambled_pass = !!(flags & SUBSCRIPTION_NODESCR);
- t->s_start_time = dispatch_clock;
+ t->s_start_time = mdispatch_clock;
pthread_mutex_lock(&t->s_stream_mutex);
service_build_filter(t);
t->s_timeout = timeout;
t->s_grace_delay = stimeout;
if (stimeout > 0)
- gtimer_arm(&t->s_receive_timer, service_data_timeout, t, stimeout);
+ mtimer_arm_rel(&t->s_receive_timer, service_data_timeout, t,
+ mono4sec(stimeout));
return 0;
}
while((st = TAILQ_FIRST(&t->s_components)) != NULL)
service_stream_destroy(t, st);
- avgstat_flush(&t->s_rate);
-
switch (t->s_type) {
case STYPE_RAW:
TAILQ_REMOVE(&service_raw_all, t, s_all_link);
t->s_type = STYPE_RAW_REMOVED;
TAILQ_REMOVE(&service_raw_all, t, s_all_link);
TAILQ_INSERT_TAIL(&service_raw_remove, t, s_all_link);
- gtimer_arm(&service_raw_remove_timer, service_remove_raw_timer_cb, NULL, 0);
+ mtimer_arm_rel(&service_raw_remove_timer, service_remove_raw_timer_cb, NULL, 0);
}
void
st->es_pid = pid;
- avgstat_init(&st->es_rate, 10);
- avgstat_init(&st->es_cc_errors, 10);
-
service_stream_make_nicename(t, st);
if(t->s_status == SERVICE_RUNNING) {
pthread_mutex_unlock(&t->s_stream_mutex);
if (t->s_timeout > 0)
- gtimer_arm(&t->s_receive_timer, service_data_timeout, t, t->s_timeout);
+ mtimer_arm_rel(&t->s_receive_timer, service_data_timeout, t,
+ mono4sec(t->s_timeout));
}
/**
int8_t es_cc; /* Last CC */
- avgstat_t es_cc_errors;
- avgstat_t es_rate;
-
int es_peak_presentation_delay; /* Max seen diff. of DTS and PTS */
/* For service stream packet reassembly */
* it will check if any packets has been parsed. If not the status
* will be set to TRANSPORT_STATUS_NO_INPUT
*/
- gtimer_t s_receive_timer;
+ mtimer_t s_receive_timer;
/**
* Stream start time
*/
- int s_timeout;
- int s_grace_delay;
- time_t s_start_time;
+ int s_timeout;
+ int s_grace_delay;
+ int64_t s_start_time;
/*********************************************************
elementary_stream_t *s_audio;
#endif
- /**
- * Average bitrate
- */
- avgstat_t s_rate;
-
/**
* Descrambling support
*/
LIST_ENTRY(spawn) link;
pid_t pid;
const char *name;
- time_t killed;
+ int64_t killed;
} spawn_t;
static void spawn_reaper(void);
/* forced kill for expired PIDs */
pthread_mutex_lock(&spawn_mutex);
LIST_FOREACH(s, &spawns, link)
- if (s->killed && s->killed < dispatch_clock) {
+ if (s->killed && s->killed < mdispatch_clock) {
/* kill the whole process group */
kill(-(s->pid), SIGKILL);
}
break;
if (s) {
if (!s->killed)
- s->killed = dispatch_clock_update(NULL) + MINMAX(timeout, 5, 3600);
+ s->killed = mdispatch_clock_update() + mono4sec(MINMAX(timeout, 5, 3600));
/* kill the whole process group */
r = kill(-pid, sig);
if (r < 0)
struct th_subscription_list subscriptions;
struct th_subscription_list subscriptions_remove;
-static gtimer_t subscription_reschedule_timer;
+static mtimer_t subscription_reschedule_timer;
static int subscription_postpone;
/**
LIST_REMOVE(s, ths_service_link);
if (stop && (s->ths_flags & SUBSCRIPTION_ONESHOT) != 0)
- gtimer_arm(&s->ths_remove_timer, subscription_unsubscribe_cb, s, 0);
+ mtimer_arm_rel(&s->ths_remove_timer, subscription_unsubscribe_cb, s, 0);
stop:
if(LIST_FIRST(&t->s_subscriptions) == NULL)
s->ths_source, s->ths_prch,
&s->ths_instances, error, s->ths_weight,
s->ths_flags, s->ths_timeout,
- dispatch_clock > s->ths_postpone_end ?
- 0 : s->ths_postpone_end - dispatch_clock);
+ mdispatch_clock > s->ths_postpone_end ?
+ 0 : sec4mono(s->ths_postpone_end - mdispatch_clock));
return s->ths_current_instance = si;
}
service_t *t;
service_instance_t *si;
streaming_message_t *sm;
- int error, postpone = INT_MAX;
+ int error, postpone = INT_MAX, postpone2;
assert(reenter == 0);
reenter = 1;
/* Postpone the tuner decision */
/* Leave some time to wakeup tuners through DBus or so */
- if (s->ths_postpone_end > dispatch_clock) {
- if (postpone > s->ths_postpone_end - dispatch_clock)
- postpone = s->ths_postpone_end - dispatch_clock;
- sm = streaming_msg_create_code(SMT_GRACE, (s->ths_postpone_end - dispatch_clock) + 5);
+ if (s->ths_postpone_end > mdispatch_clock) {
+ postpone2 = sec4mono(s->ths_postpone_end - mdispatch_clock);
+ if (postpone > postpone2)
+ postpone = postpone2;
+ sm = streaming_msg_create_code(SMT_GRACE, postpone + 5);
streaming_target_deliver(s->ths_output, sm);
continue;
}
s->ths_current_instance = si;
if(si == NULL) {
- if (s->ths_last_error != error || s->ths_last_find + 2 >= dispatch_clock) {
+ if (s->ths_last_error != error || s->ths_last_find + mono4sec(2) >= mdispatch_clock) {
tvhtrace("subscription", "%04X: instance not available, retrying", shortid(s));
if (s->ths_last_error != error)
- s->ths_last_find = dispatch_clock;
+ s->ths_last_find = mdispatch_clock;
s->ths_last_error = error;
continue;
}
if (postpone <= 0 || postpone == INT_MAX)
postpone = 2;
- gtimer_arm(&subscription_reschedule_timer,
- subscription_reschedule_cb, NULL, postpone);
+ mtimer_arm_rel(&subscription_reschedule_timer,
+ subscription_reschedule_cb, NULL, mono4sec(postpone));
reenter = 0;
}
subscription_set_postpone(void *aux, const char *path, int64_t postpone)
{
th_subscription_t *s;
- time_t now = time(NULL);
+ time_t now = mdispatch_clock_update();
+ int64_t postpone2;
if (strcmp(path, "/set"))
return -1;
/* some limits that make sense */
- if (postpone < 0)
- postpone = 0;
- if (postpone > 120)
- postpone = 120;
+ postpone = MINMAX(postpone, 0, 120);
+ postpone2 = mono4sec(postpone);
pthread_mutex_lock(&global_lock);
if (subscription_postpone != postpone) {
subscription_postpone = postpone;
- tvhinfo("subscriptions", "postpone set to %d seconds", (int)postpone);
+ tvhinfo("subscriptions", "postpone set to %"PRId64" seconds", postpone);
LIST_FOREACH(s, &subscriptions, ths_global_link) {
s->ths_postpone = postpone;
- if (s->ths_postpone_end > now && s->ths_postpone_end - now > postpone)
- s->ths_postpone_end = now + postpone;
+ if (s->ths_postpone_end > now && s->ths_postpone_end - now > postpone2)
+ s->ths_postpone_end = now + postpone2;
}
- gtimer_arm(&subscription_reschedule_timer,
- subscription_reschedule_cb, NULL, 0);
+ mtimer_arm_rel(&subscription_reschedule_timer,
+ subscription_reschedule_cb, NULL, 0);
}
pthread_mutex_unlock(&global_lock);
return postpone;
th_subscription_t *s = opaque;
if (sm->sm_type == SMT_STOP && s->ths_state != SUBSCRIPTION_ZOMBIE) {
LIST_INSERT_HEAD(&subscriptions_remove, s, ths_remove_link);
- gtimer_arm(&subscription_reschedule_timer,
- subscription_reschedule_cb, NULL, 0);
+ mtimer_arm_rel(&subscription_reschedule_timer,
+ subscription_reschedule_cb, NULL, 0);
}
streaming_msg_free(sm);
service_instance_list_clear(&s->ths_instances);
- gtimer_disarm(&s->ths_remove_timer);
+ mtimer_disarm(&s->ths_remove_timer);
if ((flags & UNSUBSCRIBE_FINAL) != 0 ||
(s->ths_flags & SUBSCRIPTION_ONESHOT) != 0)
subscription_destroy(s);
- gtimer_arm(&subscription_reschedule_timer,
- subscription_reschedule_cb, NULL, 0);
+ mtimer_arm_rel(&subscription_reschedule_timer,
+ subscription_reschedule_cb, NULL, 0);
notify_reload("subscriptions");
}
s->ths_flags = flags;
s->ths_timeout = pro ? pro->pro_timeout : 0;
s->ths_postpone = subscription_postpone;
- s->ths_postpone_end = dispatch_clock + s->ths_postpone;
+ s->ths_postpone_end = mdispatch_clock + mono4sec(s->ths_postpone);
if (s->ths_prch)
s->ths_weight = profile_chain_weight(s->ths_prch, weight);
LIST_INSERT_SORTED(&subscriptions, s, ths_global_link, subscription_sort);
- gtimer_arm(&subscription_reschedule_timer,
- subscription_reschedule_cb, NULL, 0);
+ mtimer_arm_rel(&subscription_reschedule_timer,
+ subscription_reschedule_cb, NULL, 0);
notify_reload("subscriptions");
return s;
subscription_link_service(s, si->si_s);
subscription_show_info(s);
} else {
- gtimer_arm(&subscription_reschedule_timer,
- subscription_reschedule_cb, NULL, 0);
+ mtimer_arm_rel(&subscription_reschedule_timer,
+ subscription_reschedule_cb, NULL, 0);
}
return s;
}
* Status monitoring
* *************************************************************************/
-static gtimer_t subscription_status_timer;
+static mtimer_t subscription_status_timer;
/*
* Serialize info about subscription
int64_t count = 0;
static int64_t old_count = -1;
- gtimer_arm(&subscription_status_timer,
- subscription_status_callback, NULL, 1);
+ mtimer_arm_rel(&subscription_status_timer,
+ subscription_status_callback, NULL, mono4sec(1));
LIST_FOREACH(s, &subscriptions, ths_global_link) {
/* Store the difference between total bytes from the last round */
subscription_done(void)
{
pthread_mutex_lock(&global_lock);
+ mtimer_disarm(&subscription_status_timer);
/* clear remaining subscriptions */
subscription_reschedule();
pthread_mutex_unlock(&global_lock);
LIST_INSERT_SORTED(&subscriptions, s, ths_global_link, subscription_sort);
- gtimer_arm(&subscription_reschedule_timer,
- subscription_reschedule_cb, NULL, 0);
+ mtimer_arm_rel(&subscription_reschedule_timer,
+ subscription_reschedule_cb, NULL, 0);
}
/**
streaming_msg_free(sm);
}
-static gtimer_t dummy_sub_timer;
+static mtimer_t dummy_sub_timer;
/**
*
*/
th_subscription_t *s;
if(first) {
- gtimer_arm(&dummy_sub_timer, dummy_retry, strdup(id), 2);
+ mtimer_arm_rel(&dummy_sub_timer, dummy_retry, strdup(id), mono4sec(2));
return;
}
tvhlog(LOG_ERR, "subscription",
"Unable to dummy join %s, service not found, retrying...", id);
- gtimer_arm(&dummy_sub_timer, dummy_retry, strdup(id), 1);
+ mtimer_arm_rel(&dummy_sub_timer, dummy_retry, strdup(id), mono4sec(1));
return;
}
int ths_testing_error;
- gtimer_t ths_remove_timer;
+ mtimer_t ths_remove_timer;
LIST_ENTRY(th_subscription) ths_channel_link;
struct channel *ths_channel; /* May be NULL if channel has been
int ths_flags;
int ths_timeout;
- time_t ths_last_find;
+ int64_t ths_last_find;
int ths_last_error;
streaming_message_t *ths_start_message;
/**
* Postpone
*/
- int ths_postpone;
- time_t ths_postpone_end;
+ int ths_postpone;
+ int64_t ths_postpone_end;
/*
* MPEG-TS mux chain
{
tcp_server_launch_t *tsl, *res;
uint32_t used = 0, used2;
- time_t started = dispatch_clock;
+ int64_t started = mdispatch_clock;
int c1, c2;
lock_assert(&global_lock);
c2 = aa->aa_conn_limit_streaming ? used >= aa->aa_conn_limit_streaming : -1;
if (c1 && c2) {
- if (started + 3 < dispatch_clock) {
+ if (started + mono4sec(3) < mdispatch_clock) {
tvherror("tcp", "multiple connections are not allowed for user '%s' from '%s' "
"(limit %u, streaming limit %u, active streaming %u, DVR %u)",
aa->aa_username ?: "", aa->aa_representative ?: "",
tvh_pipe_close(&tcp_server_pipe);
tvhpoll_destroy(tcp_server_poll);
- t = getmonoclock();
+ t = getfastmonoclock();
while (LIST_FIRST(&tcp_server_active) != NULL) {
- if (getmonoclock() - t > 5000000)
+ if (t + mono4sec(5) < getfastmonoclock())
tvhtrace("tcp", "tcp server %p active too long", LIST_FIRST(&tcp_server_active));
usleep(20000);
}
goto _exit;
} else {
if (ts->ref_time == 0) {
- ts->ref_time = getmonoclock();
+ ts->ref_time = getfastmonoclock();
sm->sm_time = 0;
} else {
- sm->sm_time = getmonoclock() - ts->ref_time;
+ sm->sm_time = getfastmonoclock() - ts->ref_time;
}
}
streaming_target_deliver2(&ts->wr_queue.sq_st, sm);
timeshift_file_t *tsf;
tsf = calloc(1, sizeof(timeshift_file_t));
- tsf->time = start_time / (MONOCLOCK_RESOLUTION * TIMESHIFT_FILE_PERIOD);
+ tsf->time = sec4mono(start_time) / TIMESHIFT_FILE_PERIOD;
tsf->last = start_time;
tsf->wfd = -1;
tsf->rfd = -1;
/* Store to file */
tsf_tl = TAILQ_LAST(&ts->files, timeshift_file_list);
- time = start_time / (MONOCLOCK_RESOLUTION * TIMESHIFT_FILE_PERIOD);
+ time = sec4mono(start_time) / TIMESHIFT_FILE_PERIOD;
if (!tsf_tl || tsf_tl->time < time ||
(tsf_tl->ram && tsf_tl->woff >= timeshift_conf.ram_segment_size)) {
tsf_hd = TAILQ_FIRST(&ts->files);
{
timeshift_index_iframe_t *tsi = seek->frame;
timeshift_file_t *tsf = seek->file, *tsf_last;
- int64_t sec = req_time / (MONOCLOCK_RESOLUTION * TIMESHIFT_FILE_PERIOD);
+ int64_t sec = sec4mono(req_time) / TIMESHIFT_FILE_PERIOD;
int back = (req_time < cur_time) ? 1 : 0;
int end = 0;
wait = -1;
end = 0;
skip = NULL;
- mono_now = getmonoclock();
+ mono_now = getfastmonoclock();
/* Control */
pthread_mutex_lock(&ts->state_mutex);
/* Done */
if (!run || !seek->file || ((ts->state != TS_PLAY && !skip))) {
- if (mono_now >= (mono_last_status + MONOCLOCK_RESOLUTION)) {
+ if (mono_now >= (mono_last_status + mono4sec(1))) {
timeshift_status(ts, last_time);
mono_last_status = mono_now;
}
}
/* Periodic timeshift status */
- if (mono_now >= (mono_last_status + MONOCLOCK_RESOLUTION)) {
+ if (mono_now >= (mono_last_status + mono4sec(1))) {
timeshift_status(ts, last_time);
mono_last_status = mono_now;
}
#endif
#endif
#include "queue.h"
-#include "avg.h"
#include "hts_strtab.h"
#include "htsmsg.h"
#include "tvhlog.h"
#define PICON_ISVCTYPE 1
/*
- * global timer
+ * timer support functions
+ */
+
+#if ENABLE_GTIMER_CHECK
+#define GTIMER_TRACEID_ const char *id, const char *fcn,
+#define GTIMER_FCN(n) check_##n
+#else
+#define GTIMER_TRACEID_
+#define GTIMER_FCN(n) n
+#endif
+
+/*
+ * global timer - monotonic
+ */
+
+typedef void (mti_callback_t)(void *opaque);
+
+typedef struct mtimer {
+ LIST_ENTRY(mtimer) mti_link;
+ mti_callback_t *mti_callback;
+ void *mti_opaque;
+ int64_t mti_expire;
+#if ENABLE_GTIMER_CHECK
+ const char *mti_id;
+ const char *mti_fcn;
+#endif
+} mtimer_t;
+
+void GTIMER_FCN(mtimer_arm_rel)
+ (GTIMER_TRACEID_ mtimer_t *mti, mti_callback_t *callback, void *opaque, int64_t delta);
+void GTIMER_FCN(mtimer_arm_abs)
+ (GTIMER_TRACEID_ mtimer_t *mti, mti_callback_t *callback, void *opaque, int64_t when);
+
+#if ENABLE_GTIMER_CHECK
+#define mtimer_arm_rel(a, b, c, d) GTIMER_FCN(mtimer_arm_rel)(SRCLINEID(), __func__, a, b, c, d)
+#define mtimer_arm_abs(a, b, c, d) GTIMER_FCN(mtimer_arm_abs)(SRCLINEID(), __func__, a, b, c, d)
+#endif
+
+void mtimer_disarm(mtimer_t *mti);
+
+
+
+/*
+ * global timer (based on the current system time - time())
*/
typedef void (gti_callback_t)(void *opaque);
LIST_ENTRY(gtimer) gti_link;
gti_callback_t *gti_callback;
void *gti_opaque;
- struct timespec gti_expire;
+ time_t gti_expire;
#if ENABLE_GTIMER_CHECK
const char *gti_id;
const char *gti_fcn;
#endif
} gtimer_t;
-#if ENABLE_GTIMER_CHECK
-#define GTIMER_TRACEID_ const char *id, const char *fcn,
-#define GTIMER_FCN(n) check_##n
-#else
-#define GTIMER_TRACEID_
-#define GTIMER_FCN(n) n
-#endif
-
-void GTIMER_FCN(gtimer_arm)
- (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, int delta);
-void GTIMER_FCN(gtimer_arm_ms)
- (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, long delta_ms);
-void GTIMER_FCN(gtimer_arm_abs)
+void GTIMER_FCN(gtimer_arm_rel)
+ (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t delta);
+void GTIMER_FCN(gtimer_arm_absn)
(GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t when);
-void GTIMER_FCN(gtimer_arm_abs2)
- (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, struct timespec *when);
#if ENABLE_GTIMER_CHECK
-#define gtimer_arm(a, b, c, d) GTIMER_FCN(gtimer_arm)(SRCLINEID(), __func__, a, b, c, d)
-#define gtimer_arm_ms(a, b, c, d) GTIMER_FCN(gtimer_arm_ms)(SRCLINEID(), __func__, a, b, c, d)
-#define gtimer_arm_abs(a, b, c, d) GTIMER_FCN(gtimer_arm_abs)(SRCLINEID(), __func__, a, b, c, d)
-#define gtimer_arm_abs2(a, b, c, d) GTIMER_FCN(gtimer_arm_abs2)(SRCLINEID(), __func__, a, b, c, d)
+#define gtimer_arm_rel(a, b, c, d) GTIMER_FCN(gtimer_arm_rel)(SRCLINEID(), __func__, a, b, c, d)
+#define gtimer_arm_absn(a, b, c, d) GTIMER_FCN(gtimer_arm_absn)(SRCLINEID(), __func__, a, b, c, d)
#endif
void gtimer_disarm(gtimer_t *gti);
void tvh_str_set(char **strp, const char *src);
int tvh_str_update(char **strp, const char *src);
-#ifndef CLOCK_MONOTONIC_COARSE
-#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
-#endif
-
-#ifdef PLATFORM_DARWIN
-#define CLOCK_MONOTONIC 0
-#define CLOCK_REALTIME 0
-
-static inline int clock_gettime(int clk_id, struct timespec* t) {
- struct timeval now;
- int rv = gettimeofday(&now, NULL);
- if (rv) return rv;
- t->tv_sec = now.tv_sec;
- t->tv_nsec = now.tv_usec * 1000;
- return 0;
-}
-#endif
-
-#define MONOCLOCK_RESOLUTION 1000000LL /* microseconds */
-
-static inline int64_t
-getmonoclock(void)
-{
- struct timespec tp;
-
- clock_gettime(CLOCK_MONOTONIC_COARSE, &tp);
-
- return tp.tv_sec * MONOCLOCK_RESOLUTION +
- (tp.tv_nsec / (1000000000LL/MONOCLOCK_RESOLUTION));
-}
-
int sri_to_rate(int sri);
int rate_to_sri(int rate);
-
extern struct service_list all_transports;
extern void scopedunlock(pthread_mutex_t **mtxp);
#define PRItime_t "ld"
#endif
-void time_t_out_of_range_notify(int64_t val);
-
-static inline time_t time_t_out_of_range(uint64_t val)
-{
- time_t r = val;
- if ((int64_t)r != val) {
- time_t_out_of_range_notify(val);
- r = INT32_MAX;
- }
- return r;
-}
-
#endif /* TVHEADEND_H */
#include "libav.h"
#include "webui/webui.h"
-time_t dispatch_clock;
+int64_t mdispatch_clock;
+time_t gdispatch_clock;
int tvhlog_run;
int tvhlog_level;
#include <time.h>
#include "atomic.h"
+#include "clock.h"
#include "htsmsg.h"
typedef struct {
- time_t last;
+ int64_t last;
size_t count;
} tvhlog_limit_t;
-/* Globals */
-extern time_t dispatch_clock;
-
/* Config */
extern int tvhlog_level;
extern htsmsg_t *tvhlog_debug;
static inline void tvhlog_limit_reset ( tvhlog_limit_t *limit )
{ limit->last = 0; limit->count = 0; }
static inline int tvhlog_limit ( tvhlog_limit_t *limit, uint32_t delay )
- { time_t t = dispatch_clock; limit->count++;
- if (limit->last + delay < t) { limit->last = t; return 1; }
+ { int64_t t = mdispatch_clock; limit->count++;
+ if (limit->last + (int64_t)delay * MONOCLOCK_RESOLUTION < t)
+ { limit->last = t; return 1; }
return 0; }
#define tvherror(...) tvhlog(LOG_ERR, ##__VA_ARGS__)
#define tvhalert(...) tvhlog(LOG_ALERT, ##__VA_ARGS__)
-time_t dispatch_clock_update(struct timespec *ts);
-
void tvhlog_backtrace_printf(const char *fmt, ...);
#endif /* __TVH_LOGGING_H__ */
char *cmb_boxid; /* SHA-1 hash */
char *cmb_lang; /* UI language */
htsmsg_t *cmb_messages; /* A vector */
- time_t cmb_last_used;
+ int64_t cmb_last_used;
LIST_ENTRY(comet_mailbox) cmb_link;
int cmb_debug;
} comet_mailbox_t;
for(cmb = LIST_FIRST(&mailboxes); cmb != NULL; cmb = next) {
next = LIST_NEXT(cmb, cmb_link);
- if(cmb->cmb_last_used && cmb->cmb_last_used + 60 < dispatch_clock)
+ if(cmb->cmb_last_used && cmb->cmb_last_used + mono4sec(60) < mdispatch_clock)
cmb_destroy(cmb);
}
pthread_mutex_unlock(&comet_mutex);
cmb->cmb_boxid = strdup(id);
cmb->cmb_lang = lang ? strdup(lang) : NULL;
- time(&cmb->cmb_last_used);
+ cmb->cmb_last_used = mdispatch_clock;
mailbox_tally++;
LIST_INSERT_HEAD(&mailboxes, cmb, cmb_link);
comet_mailbox_t *cmb = NULL;
const char *cometid = http_arg_get(&hc->hc_req_args, "boxid");
const char *immediate = http_arg_get(&hc->hc_req_args, "immediate");
- int im = immediate ? atoi(immediate) : 0;
+ int im = immediate ? atoi(immediate) : 0, e;
+ int64_t mono;
htsmsg_t *m;
if(!im)
cmb->cmb_last_used = 0; /* Make sure we're not flushed out */
if(!im && cmb->cmb_messages == NULL) {
- tvh_cond_timedwait(&comet_cond, &comet_mutex,
- getmonoclock() + 10 * MONOCLOCK_RESOLUTION);
+ mono = mdispatch_clock + mono4sec(10);
+ do {
+ e = tvh_cond_timedwait(&comet_cond, &comet_mutex, mono);
+ if (e == ETIMEDOUT)
+ break;
+ } while (ERRNO_AGAIN(e));
if (!comet_running) {
pthread_mutex_unlock(&comet_mutex);
return 400;
htsmsg_add_msg(m, "messages", cmb->cmb_messages ?: htsmsg_create_list());
cmb->cmb_messages = NULL;
- cmb->cmb_last_used = dispatch_clock;
+ cmb->cmb_last_used = mdispatch_clock;
pthread_mutex_unlock(&comet_mutex);
const char *name, th_subscription_t *s)
{
streaming_message_t *sm;
- int run = 1;
- int started = 0;
+ int run = 1, started = 0;
streaming_queue_t *sq = &prch->prch_sq;
muxer_t *mux = prch->prch_muxer;
- time_t lastpkt;
- int ptimeout, grace = 20;
+ int ptimeout, grace = 20, r;
struct timeval tp;
streaming_start_t *ss_copy;
- int64_t mono;
+ int64_t lastpkt, mono;
if(muxer_open_stream(mux, hc->hc_fd))
run = 0;
if (config.dscp >= 0)
socket_set_dscp(hc->hc_fd, config.dscp, NULL, 0);
- lastpkt = dispatch_clock;
+ lastpkt = mdispatch_clock;
ptimeout = prch->prch_pro ? prch->prch_pro->pro_timeout : 5;
if (hc->hc_no_output) {
pthread_mutex_lock(&sq->sq_mutex);
sm = TAILQ_FIRST(&sq->sq_queue);
if(sm == NULL) {
- if(tvh_cond_timedwait(&sq->sq_cond, &sq->sq_mutex,
- getmonoclock() + 1 * MONOCLOCK_RESOLUTION) == ETIMEDOUT) {
- /* Check socket status */
- if (tcp_socket_dead(hc->hc_fd)) {
- tvhlog(LOG_DEBUG, "webui", "Stop streaming %s, client hung up", hc->hc_url_orig);
- run = 0;
- } else if((!started && dispatch_clock - lastpkt > grace) ||
- (started && ptimeout > 0 && dispatch_clock - lastpkt > ptimeout)) {
- tvhlog(LOG_WARNING, "webui", "Stop streaming %s, timeout waiting for packets", hc->hc_url_orig);
- run = 0;
+ mono = mdispatch_clock + mono4sec(1);
+ do {
+ r = tvh_cond_timedwait(&sq->sq_cond, &sq->sq_mutex, mono);
+ if (r == ETIMEDOUT) {
+ /* Check socket status */
+ if (tcp_socket_dead(hc->hc_fd)) {
+ tvhlog(LOG_DEBUG, "webui", "Stop streaming %s, client hung up", hc->hc_url_orig);
+ run = 0;
+ } else if((!started && mdispatch_clock - lastpkt > mono4sec(grace)) ||
+ (started && ptimeout > 0 && mdispatch_clock - lastpkt > mono4sec(ptimeout))) {
+ tvhlog(LOG_WARNING, "webui", "Stop streaming %s, timeout waiting for packets", hc->hc_url_orig);
+ run = 0;
+ }
+ break;
}
- }
+ } while (ERRNO_AGAIN(r));
pthread_mutex_unlock(&sq->sq_mutex);
continue;
}
pb = sm->sm_data;
subscription_add_bytes_out(s, len = pktbuf_len(pb));
if (len > 0)
- lastpkt = dispatch_clock;
+ lastpkt = mdispatch_clock;
muxer_write_pkt(mux, sm->sm_type, sm->sm_data);
sm->sm_data = NULL;
}
if (hc->hc_no_output) {
streaming_msg_free(sm);
- mono = getmonoclock() + 2000000;
- while (getmonoclock() < mono) {
+ mono = getfastmonoclock() + mono4sec(2);
+ while (getfastmonoclock() < mono) {
if (tcp_socket_dead(hc->hc_fd))
break;
usleep(50000);
tvhlog(LOG_DEBUG, "webui", "Stop streaming %s, client hung up",
hc->hc_url_orig);
run = 0;
- } else if((!started && dispatch_clock - lastpkt > grace) ||
- (started && ptimeout > 0 && dispatch_clock - lastpkt > ptimeout)) {
+ } else if((!started && mdispatch_clock - lastpkt > mono4sec(grace)) ||
+ (started && ptimeout > 0 && mdispatch_clock - lastpkt > mono4sec(ptimeout))) {
tvhlog(LOG_WARNING, "webui", "Stop streaming %s, timeout waiting for packets", hc->hc_url_orig);
run = 0;
}
int
tvh_write(int fd, const void *buf, size_t len)
{
- time_t next = dispatch_clock + 25;
+ int64_t limit = mdispatch_clock + mono4sec(25);
ssize_t c;
while (len) {
c = write(fd, buf, len);
if (c < 0) {
if (ERRNO_AGAIN(errno)) {
- if (dispatch_clock > next)
+ if (mdispatch_clock > limit)
break;
usleep(100);
- dispatch_clock_update(NULL);
continue;
}
break;
tvh_mutex_timedlock
( pthread_mutex_t *mutex, int64_t usec )
{
- int64_t finish = getmonoclock() + usec;
+ int64_t finish = getfastmonoclock() + usec;
int retcode;
while ((retcode = pthread_mutex_trylock (mutex)) == EBUSY) {
- if (getmonoclock() >= finish)
+ if (getfastmonoclock() >= finish)
return ETIMEDOUT;
usleep(10000);