/** * As tor_gettimeofday_cached, but can never move backwards in time. * * The returned value may diverge from wall-clock time, since wall-clock time * can trivially be adjusted backwards, and this can't. Don't mix wall-clock * time with these values in the same calculation. * * Depending on implementation, this function may or may not "smooth out" huge * jumps forward in wall-clock time. It may or may not keep its results * advancing forward (as opposed to stalling) if the wall-clock time goes * backwards. The current implementation does neither of of these. * * This function is not thread-safe; do not call it outside the main thread. * * In future versions of Tor, this may return a time does not have its * origin at the Unix epoch. */ void tor_gettimeofday_cached_monotonic(struct timeval *tv) { struct timeval last_tv = { 0, 0 }; tor_gettimeofday_cached(tv); if (timercmp(tv, &last_tv, OP_LT)) { memcpy(tv, &last_tv, sizeof(struct timeval)); } else { memcpy(&last_tv, tv, sizeof(struct timeval)); } }
/** * Process scheduled callbacks up to current time. * * @return The number of milliseconds untill the next scheduled event * or -1 for no event. */ int schedule_run(void) { struct timeval tv; struct timeval nexttime; struct timeval rettime; struct nscallback *cur_nscb; struct nscallback *prev_nscb; struct nscallback *unlnk_nscb; if (schedule_list == NULL) return -1; /* reset enumeration to the start of the list */ cur_nscb = schedule_list; prev_nscb = NULL; nexttime = cur_nscb->tv; gettimeofday(&tv, NULL); while (cur_nscb != NULL) { if (timercmp(&tv, &cur_nscb->tv, 0)) { /* scheduled time */ /* remove callback */ unlnk_nscb = cur_nscb; if (prev_nscb == NULL) { schedule_list = unlnk_nscb->next; } else { prev_nscb->next = unlnk_nscb->next; } unlnk_nscb->callback(unlnk_nscb->p); free(unlnk_nscb); /* need to deal with callback modifying the list. */ if (schedule_list == NULL) return -1; /* no more callbacks scheduled */ /* reset enumeration to the start of the list */ cur_nscb = schedule_list; prev_nscb = NULL; nexttime = cur_nscb->tv; } else { /* if the time to the event is sooner than the * currently recorded soonest event record it */ if (timercmp(&nexttime, &cur_nscb->tv, 0)) { nexttime = cur_nscb->tv; } /* move to next element */ prev_nscb = cur_nscb; cur_nscb = prev_nscb->next; } } /* make rettime relative to now */ timersub(&nexttime, &tv, &rettime); /*LOG(("returning time to next event as %ldms",(rettime.tv_sec * 1000) + (rettime.tv_usec / 1000))); */ /* return next event time in milliseconds (24days max wait) */ return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000); }