static void wakeup_cb(mrp_wakeup_t *w, mrp_wakeup_event_t event, void *user_data) { static struct timeval prev[2] = { {0, 0}, {0, 0} }; const char *evt; struct timeval now; double diff; int id; MRP_UNUSED(w); MRP_UNUSED(user_data); timeval_now(&now); switch (event) { case MRP_WAKEUP_EVENT_TIMER: evt = "timer"; break; case MRP_WAKEUP_EVENT_IO: evt = "I/O (or signal)"; break; case MRP_WAKEUP_EVENT_LIMIT: evt = "limit"; break; default: evt = "???"; } id = user_data ? 1 : 0; if (MRP_LIKELY(prev[id].tv_usec != 0)) { diff = timeval_diff(&now, &prev[id]) / 1000.0; info("woken up #%d by %s, %.2f msecs since previous", id, evt, diff); } prev[id] = now; }
static gboolean glib_timer_cb(gpointer user_data) { glib_timer_t *t = (glib_timer_t *)user_data; struct timeval now; double diff, error; timeval_now(&now); diff = timeval_diff(&now, &t->prev) / 1000.0; error = diff - t->interval; if (error < 0.0) error = -error; info("GLIB timer #%d: %d/%d, diff %.2f (lag %.2f, %.3f %%)", t->id, t->count, t->target, diff, error, 100 * error / diff); t->count++; t->prev = now; if (t->count >= t->target) { info("GLIB timer #%d has finished.", t->id); t->gsrc = 0; cfg.nrunning--; return FALSE; } else return TRUE; }
void timer_cb(mrp_timer_t *timer, void *user_data) { test_timer_t *t = (test_timer_t *)user_data; struct timeval now; double diff, error; MRP_UNUSED(timer); timeval_now(&now); diff = timeval_diff(&now, &t->prev) / 1000.0; error = diff - t->interval; if (error < 0.0) error = -error; info("MRPH timer #%d: %d/%d, diff %.2f (lag %.2f, %.3f %%)", t->id, t->count, t->target, diff, error, 100 * error / diff); t->count++; t->prev = now; if (t->count >= t->target) { info("MRPH timer #%d has finished.", t->id); mrp_del_timer(t->timer); t->timer = NULL; cfg.nrunning--; } }
void cron_init(void) { cron_info.chunk_job = memchunk_new("cron/job", sizeof (Job), 8); timeval_now(&cron_info.epoch); cron_info.now = cron_info.epoch; cron_info.id_next = 1; cron_info.id_reuse = NULL; cron_info.oneshot = NULL; cron_info.periodic = NULL; }
void cron_update(void) { TimeVal now; double dt; List *iter, *next; timeval_now(&now); dt = timeval_elapsed(&cron_info.now, &now); for(iter = cron_info.oneshot; iter != NULL; iter = next) { Job *job = list_data(iter); next = list_next(iter); if(timeval_passed(&job->when.oneshot, &now)) { if(job->handler == (int (*)(void *)) printf) printf("%s\n", (const char *) job->data); else job->handler(job->data); job_remove(&cron_info.oneshot, iter); } } for(iter = cron_info.periodic; iter != NULL; iter = next) { Job *job = list_data(iter); next = list_next(iter); job->when.periodic.bucket += dt; if(job->when.periodic.bucket >= job->when.periodic.period) { if(job->handler == (int (*)(void *)) printf) /* Clever? */ printf("%s\n", (const char *) job->data); else { if(!job->handler(job->data)) job_remove(&cron_info.periodic, iter); else job->when.periodic.bucket = 0.0; } } } cron_info.now = now; }
/* Usually called from the timer callback of @progress->timer. */ void update_progress(struct progress *progress, off_t loaded, off_t size, off_t pos) { off_t bytes_delta; timeval_T now, elapsed, dis_b_max, dis_b_interval; timeval_now(&now); timeval_sub(&elapsed, &progress->last_time, &now); timeval_copy(&progress->last_time, &now); progress->loaded = loaded; bytes_delta = progress->loaded - progress->last_loaded; progress->last_loaded = progress->loaded; timeval_add_interval(&progress->elapsed, &elapsed); timeval_add_interval(&progress->dis_b, &elapsed); timeval_from_milliseconds(&dis_b_max, mult_ms(SPD_DISP_TIME, CURRENT_SPD_SEC)); timeval_from_milliseconds(&dis_b_interval, SPD_DISP_TIME); while (timeval_cmp(&progress->dis_b, &dis_b_max) >= 0) { progress->cur_loaded -= progress->data_in_secs[0]; memmove(progress->data_in_secs, progress->data_in_secs + 1, sizeof(*progress->data_in_secs) * (CURRENT_SPD_SEC - 1)); progress->data_in_secs[CURRENT_SPD_SEC - 1] = 0; timeval_sub_interval(&progress->dis_b, &dis_b_interval); } progress->data_in_secs[CURRENT_SPD_SEC - 1] += bytes_delta; progress->cur_loaded += bytes_delta; progress->current_speed = progress->cur_loaded / (CURRENT_SPD_SEC * ((long) SPD_DISP_TIME) / 1000); progress->pos = pos; progress->size = size; if (progress->size != -1 && progress->size < progress->pos) progress->size = progress->pos; progress->average_speed = timeval_div_off_t(progress->loaded, &progress->elapsed); if (progress->average_speed) /* Division by zero risk */ timeval_from_seconds(&progress->estimated_time, (progress->size - progress->pos) / progress->average_speed); install_timer(&progress->timer, SPD_DISP_TIME, progress_timeout, progress); }
/*! Unlike in install_timer(), @a timer_func need not erase the * expired timer ID from @a progress->timer. update_progress() * installs the timer with a wrapper function that takes care of * erasing the timer ID. */ void start_update_progress(struct progress *progress, void (*timer_func)(void *), void *timer_func_data) { if (!progress->valid) { struct progress tmp; /* Just copy useful fields from invalid progress. */ memset(&tmp, 0, sizeof(tmp)); tmp.start = progress->start; tmp.seek = progress->seek; tmp.valid = 1; memcpy(progress, &tmp, sizeof(*progress)); } timeval_now(&progress->last_time); progress->last_loaded = progress->loaded; progress->timer_func = timer_func; progress->timer_func_data = timer_func_data; }
static void setup_glib_timers(void) { glib_timer_t *t; int intervals[] = { GTIMER_INTERVALS, 0 }, *iv = intervals; int msecs, i; if ((gtimers = mrp_allocz_array(glib_timer_t, cfg.ngtimer)) != NULL) { for (i = 0, t = gtimers; i < cfg.ngtimer; i++, t++) { t->id = i; msecs = *iv; while (cfg.runtime / msecs < 1 && msecs > 0) msecs /= 2; msecs *= 1000; if (!msecs) msecs = 500; t->interval = msecs; t->target = 1000 * cfg.runtime / msecs; if (!t->target) continue; timeval_now(&t->prev); t->gsrc = g_timeout_add(msecs, glib_timer_cb, t); if (t->gsrc != 0) info("GLIB timer #%d: interval=%d, target=%d", t->id, *iv, t->target); else fatal("GLIB timer #%d: failed to create", t->id); cfg.nrunning++; iv++; if (!*iv) iv = intervals; } } else if (cfg.ntimer > 0) fatal("could not allocate %d GLIB timers", cfg.ngtimer); }
static void setup_timers(mrp_mainloop_t *ml) { test_timer_t *t; int intervals[] = { TIMER_INTERVALS, 0 }, *iv = intervals; int msecs, i; if ((timers = mrp_allocz_array(test_timer_t, cfg.ntimer)) != NULL) { for (i = 0, t = timers; i < cfg.ntimer; i++, t++) { t->id = i; msecs = *iv; while (cfg.runtime / msecs < 1 && msecs > 0) msecs /= 2; msecs *= 1000; if (!msecs) msecs = 500; t->interval = msecs; t->target = 1000 * cfg.runtime / msecs; if (!t->target) continue; timeval_now(&t->prev); t->timer = mrp_add_timer(ml, t->interval, timer_cb, t); if (t->timer != NULL) info("MRPH timer #%d: interval=%d, target=%d", t->id, *iv, t->target); else fatal("MRPH timer #%d: failed to create", t->id); cfg.nrunning++; iv++; if (!*iv) iv = intervals; } } else if (cfg.ntimer > 0) fatal("could not allocate %d timers", cfg.ntimer); }
void sync_update(double slice) { List *iter, *next; PNode *n; TimeVal now; /* Create nodes that need to be created. */ for(iter = sync_info.queue_create; iter != NULL; iter = next) { next = list_next(iter); n = list_data(iter); verse_send_node_create(~0, n->type, 0); /* Move node from "to create" to "pending" list; no change in refcount. */ sync_info.queue_create = list_unlink(sync_info.queue_create, iter); list_destroy(iter); sync_info.queue_create_pend = list_prepend(sync_info.queue_create_pend, n); } /* Synchronize existing nodes. */ timeval_now(&now); for(iter = sync_info.queue_sync; iter != NULL; iter = next) { PNode *n = list_data(iter); next = list_next(iter); if(timeval_elapsed(&n->sync.last_send, &now) < 0.1) continue; n->sync.last_send = now; if(sync_node(n)) { sync_info.queue_sync = list_unlink(sync_info.queue_sync, iter); printf("removing node %u from sync queue, it's in sync\n", n->id); nodedb_unref(n); list_destroy(iter); n->sync.busy = 0; } } }