int tvh_write(int fd, const void *buf, size_t len) { time_t next = dispatch_clock + 25; ssize_t c; while (len) { c = write(fd, buf, len); if (c < 0) { if (ERRNO_AGAIN(errno)) { if (dispatch_clock > next) break; usleep(100); dispatch_clock_update(NULL); continue; } break; } len -= c; buf += c; } return len ? 1 : 0; }
static void mainloop(void) { gtimer_t *gti; gti_callback_t *cb; struct timespec ts; #if ENABLE_GTIMER_CHECK int64_t mtm; const char *id; const char *fcn; #endif while(tvheadend_running) { dispatch_clock_update(&ts); /* Global timers */ pthread_mutex_lock(&global_lock); // TODO: there is a risk that if timers re-insert themselves to // 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); LIST_FOREACH(gti, >imers, gti_link) tvhdebug("gtimer", " gti %p expire %ld.%08ld", gti, gti->gti_expire.tv_sec, gti->gti_expire.tv_nsec); #endif 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; break; } #if ENABLE_GTIMER_CHECK mtm = getmonoclock(); id = gti->gti_id; fcn = gti->gti_fcn; #endif cb = gti->gti_callback; LIST_REMOVE(gti, gti_link); gti->gti_callback = NULL; cb(gti->gti_opaque); #if ENABLE_GTIMER_CHECK tvhtrace("gtimer", "%s:%s duration %"PRId64"ns", id, fcn, getmonoclock() - mtm); #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); } }