return r;
}
+void tvh_safe_usleep(int64_t us);
+
+int64_t tvh_usleep(int64_t us);
+int64_t tvh_usleep_abs(int64_t us);
+
#endif /* TVHEADEND_CLOCK_H */
code = -ENOENT;
} else {
while ((code = spawn_reap(pid, errtxt, sizeof(errtxt))) == -EAGAIN)
- usleep(20000);
+ tvh_safe_usleep(20000);
if (code == -ECHILD)
code = 0;
tvhinfo("config", "backup: completed");
pthread_mutex_unlock(&global_lock);
/* Classic authentication failed delay */
- usleep(250000);
+ tvh_safe_usleep(250000);
reply = htsmsg_create_map();
htsmsg_add_u32(reply, "noaccess", 1);
if (r == 0)
break;
if (r == EBUSY)
- usleep(10000);
+ tvh_safe_usleep(10000);
}
return 1;
}
if (!i) {
for (j = 0; j < MAX_DEV_OPEN_ATTEMPTS; j++) {
if (!access(fe_path, R_OK | W_OK)) break;
- usleep(100000);
+ tvh_safe_usleep(100000);
}
}
if (access(fe_path, R_OK | W_OK)) continue;
/* Get frontend info */
for (j = 0; j < MAX_DEV_OPEN_ATTEMPTS; j++) {
if ((fd = tvh_open(fe_path, O_RDWR, 0)) >= 0) break;
- usleep(100000);
+ tvh_safe_usleep(100000);
}
if (fd < 0) {
tvhlog(LOG_ERR, "linuxdvb", "unable to open %s", fe_path);
/* Get ca info */
for (j = 0; j < MAX_DEV_OPEN_ATTEMPTS; j++) {
if ((fd = tvh_open(ca_path, O_RDWR, 0)) >= 0) break;
- usleep(100000);
+ tvh_safe_usleep(100000);
}
if (fd < 0) {
tvhlog(LOG_ERR, "linuxdvb", "unable to open %s", ca_path);
tvherror("en50494","failed to lock for tuning");
return -1;
}
- usleep(20000);
+ tvh_safe_usleep(20000);
}
/* setup en50494 switch */
uint8_t rnd;
uuid_random(&rnd, 1);
int ms = ((int)rnd)%50 + 68;
- usleep(ms*1000);
+ tvh_safe_usleep(ms*1000);
}
/* use 18V */
tvherror("en50494", "error setting lnb voltage to 18V");
break;
}
- usleep(15000); /* standard: 4ms < x < 22ms */
+ tvh_safe_usleep(15000); /* standard: 4ms < x < 22ms */
/* send tune command (with/without pin) */
tvhdebug("en50494",
tvherror("en50494", "error send tune command");
break;
}
- usleep(50000); /* standard: 2ms < x < 60ms */
+ tvh_safe_usleep(50000); /* standard: 2ms < x < 60ms */
/* return to 13V */
ret = linuxdvb_diseqc_set_volt(lsp, 0);
rep = lfe->lfe_tune_repeats > 0 ? lfe->lfe_tune_repeats : 0;
for (i = 0; i <= rep; i++) {
if (i > 0)
- usleep(15000);
+ tvh_safe_usleep(15000);
r = linuxdvb_frontend_tune0(lfe, mmi, freq);
if (r)
break;
tvherror("diseqc", "failed to set GOTOX pos %d", lr->lr_position);
return -1;
}
- usleep(MINMAX(lr->lr_cmd_time, 10, 100) * 1000);
+ tvh_safe_usleep(MINMAX(lr->lr_cmd_time, 10, 100) * 1000);
}
tvhdebug("diseqc", "rotor GOTOX pos %d sent", lr->lr_position);
tvherror("diseqc", "failed to send USALS command");
return -1;
}
- usleep(MINMAX(lr->lr_cmd_time, 10, 100) * 1000);
+ tvh_safe_usleep(MINMAX(lr->lr_cmd_time, 10, 100) * 1000);
}
return linuxdvb_rotor_grace((linuxdvb_diseqc_t*)lr,lm);
/* the linuxdvb_diseqc_set_volt() fcn already sleeps for 15ms */
if (delay > 15) {
tvhtrace("diseqc", "initial sleep %dms", delay);
- usleep((delay-15)*1000);
+ tvh_safe_usleep((delay-15)*1000);
}
return 0;
}
return -1;
}
ls->ls_last_tone_off = band + 1;
- usleep(20000); // Allow LNB to settle before tuning
+ tvh_safe_usleep(20000); // Allow LNB to settle before tuning
}
}
return -1;
}
if (vol >= 0)
- usleep(15000);
+ tvh_safe_usleep(15000);
ls->ls_last_vol = vol ? (vol < 0 ? 0 : 2) : 1;
return 0;
}
if (linuxdvb_diseqc_send(fd, 0xE0 | r2, 0x10, 0x39, 1,
0xF0 | ls->ls_uncommitted))
return -1;
- usleep(slp);
+ tvh_safe_usleep(slp);
}
/* Committed */
if (ls->ls_committed >= 0) {
if (linuxdvb_diseqc_send(fd, 0xE0 | r1, 0x10, 0x38, 1, com))
return -1;
- usleep(slp);
+ tvh_safe_usleep(slp);
}
if (!ls->ls_uncommitted_first) {
if (linuxdvb_diseqc_send(fd, 0xE0 | r2, 0x10, 0x39, 1,
0xF0 | ls->ls_uncommitted))
return -1;
- usleep(slp);
+ tvh_safe_usleep(slp);
}
}
sbuf_t buf;
mpegts_pcr_t pcr;
int64_t pcr_last = PTS_UNSET;
-#if PLATFORM_LINUX
- int64_t pcr_last_realtime = 0;
-#endif
+ int64_t pcr_last_mono = 0;
tsfile_input_t *mi = aux;
mpegts_mux_instance_t *mmi;
tsfile_mux_instance_t *tmi;
len = 0;
tvhtrace("tsfile", "adapter %d file size %jd rem %zu",
mi->mi_instance, (intmax_t)st.st_size, rem);
+
+ pcr_last_mono = getfastmonoclock();
/* Process input */
while (1) {
/* Delay */
if (pcr.pcr_first != PTS_UNSET) {
if (pcr_last != PTS_UNSET) {
- struct timespec slp;
- int64_t delta;
+ int64_t delta, r;
delta = pcr.pcr_first - pcr_last;
delta = 90000;
delta *= 11;
-#if PLATFORM_LINUX
- delta += pcr_last_realtime;
- slp.tv_sec = (delta / 1000000);
- slp.tv_nsec = (delta % 1000000) * 1000;
- clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &slp, NULL);
-#else
- slp.tv_sec = (delta / 1000000);
- slp.tv_nsec = (delta % 1000000) * 1000;
- nanosleep(&slp, NULL);
-#endif
+ do {
+ r = tvh_usleep_abs(pcr_last_mono + delta);
+ } while (ERRNO_AGAIN(r) || r > 0);
}
- pcr_last = pcr.pcr_first;
-#if PLATFORM_LINUX
- pcr_last_realtime = getfastmonoclock();
-#endif
+ pcr_last = pcr.pcr_first;
+ pcr_last_mono = getfastmonoclock();
}
}
sched_yield();
htsmsg_destroy(q);
/* Wait */
- usleep(500000);
+ tvh_safe_usleep(500000);
pthread_mutex_lock(¬ify_mutex);
}
pthread_mutex_unlock(¬ify_mutex);
satip_rtcp_thread(void *aux)
{
satip_rtp_session_t *rtp;
- struct timespec ts;
+ int64_t us;
uint8_t msg[RTCP_PAYLOAD+1];
char addrbuf[50];
int r, len, err;
tvhtrace("satips", "starting rtcp thread");
while (satip_rtcp_run) {
- ts.tv_sec = 0;
- ts.tv_nsec = 150000000;
+ us = 150000;
do {
- r = nanosleep(&ts, &ts);
+ us = tvh_usleep(us);
+ if (us < 0)
+ goto end;
if (!satip_rtcp_run)
goto end;
- } while (r && ts.tv_nsec);
+ } while (us > 0);
pthread_mutex_lock(&satip_rtp_lock);
TAILQ_FOREACH(rtp, &satip_rtp_sessions, link) {
if (rtp->sq == NULL) continue;
return NULL;
}
pthread_mutex_unlock(&global_lock);
- usleep(250000);
+ tvh_safe_usleep(250000);
pthread_mutex_lock(&global_lock);
if (tvheadend_running)
goto try_again;
while (LIST_FIRST(&tcp_server_active) != NULL) {
if (t + sec2mono(5) < getfastmonoclock())
tvhtrace("tcp", "tcp server %p active too long", LIST_FIRST(&tcp_server_active));
- usleep(20000);
+ tvh_safe_usleep(20000);
}
pthread_mutex_lock(&global_lock);
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
if (r < 0) {
if (ERRNO_AGAIN(errno)) {
- usleep(100);
+ tvh_safe_usleep(100);
continue;
}
break;
pthread_mutex_unlock(&upnp_lock);
if (data == NULL)
break;
- usleep((long)data->delay_ms * 1000);
+ tvh_safe_usleep((long)data->delay_ms * 1000);
upnp_dump_data(data);
udp_write_queue(unicast, &data->queue, &data->storage);
htsbuf_queue_flush(&data->queue);
htsmsg_t *m;
if(!im)
- usleep(100000); /* Always sleep 0.1 sec to avoid comet storms */
+ tvh_safe_usleep(100000); /* Always sleep 0.1 sec to avoid comet storms */
pthread_mutex_lock(&comet_mutex);
if (!comet_running) {
while (getfastmonoclock() < mono) {
if (tcp_socket_dead(hc->hc_fd))
break;
- usleep(50000);
+ tvh_safe_usleep(50000);
}
return;
}
if (ERRNO_AGAIN(errno)) {
if (mdispatch_clock > limit)
break;
- usleep(100);
+ tvh_safe_usleep(100);
continue;
}
break;
if (getfastmonoclock() >= finish)
return ETIMEDOUT;
- usleep(10000);
+ tvh_safe_usleep(10000);
}
return retcode;
return pthread_cond_timedwait(&cond->cond, mutex, &ts);
}
+/*
+ * clocks
+ */
+
+void
+tvh_safe_usleep(int64_t us)
+{
+ int64_t r;
+ if (us <= 0)
+ return;
+ do {
+ r = tvh_usleep(us);
+ if (r < 0) {
+ if (ERRNO_AGAIN(r))
+ continue;
+ break;
+ }
+ us = r;
+ } while (r > 0);
+}
+
+int64_t
+tvh_usleep(int64_t us)
+{
+ struct timespec ts;
+ int64_t val;
+ int r;
+ if (us <= 0)
+ return 0;
+ ts.tv_sec = us / 1000000LL;
+ ts.tv_nsec = (us % 1000000LL) * 1000LL;
+ r = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts);
+ val = (ts.tv_sec * 1000000LL) + ((ts.tv_nsec + 500LL) / 1000LL);
+ if (ERRNO_AGAIN(r))
+ return val;
+ return r ? -r : 0;
+}
+
+int64_t
+tvh_usleep_abs(int64_t us)
+{
+ struct timespec ts;
+ int64_t val;
+ int r;
+ if (us <= 0)
+ return 0;
+ ts.tv_sec = us / 1000000LL;
+ ts.tv_nsec = (us % 1000000LL) * 1000LL;
+ r = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, &ts);
+ val = (ts.tv_sec * 1000000LL) + ((ts.tv_nsec + 500LL) / 1000LL);
+ if (ERRNO_AGAIN(r))
+ return val;
+ return r ? -r : 0;
+}
+
/*
* qsort
*/