/* * start_timer() * * Starts a new timer with given expiration time, callback function, * and arguments. Returns a pointer to the new timer, which must be kept * to stop the timer later if desired. */ void start_timer(timer *tptr, int seconds_to_expiry, timer_callback cb, void *cb_arg) { timer_links *next, *prev; /* * See if this timer is also running. */ next = tptr->links.next; if (next) { prev = tptr->links.prev; next->prev = prev; prev->next = next; /* * Update stats */ timer_wheel.running_timers--; } /* * Hook up the callback */ tptr->cb = cb; tptr->cb_argument = cb_arg; tptr->duration = seconds_to_expiry; insert_timer(tptr); timer_wheel.running_timers++; return; }
static void run_timer_event(void) { assert(timers_suspended); double n = now(); retry: if (nr_timers_pending == 0) return; double nextFire = pendingTimers[0]->nextDue; for (int idx = 0; idx < nr_timers_pending; idx++) { Timer *pt = pendingTimers[idx]; if (!pt->inserted) { abort(); } if (pt->nextDue <= n) { kill_timer(pt); if (pt->interval > 0) { pt->nextDue = n + pt->interval; insert_timer(pt); } pt->fired(); goto retry; } if (pt->nextDue < nextFire) nextFire = pt->nextDue; } n = now(); if (n >= nextFire) goto retry; struct itimerval itv; memset(&itv, 0, sizeof(itv)); itv.it_value.tv_sec = nextFire - n; itv.it_value.tv_usec = (nextFire - n - itv.it_value.tv_sec) * 1e6; while (itv.it_value.tv_usec >= 1000000) { /* Shouldn't really happen, but might conceivably if we're in a funny rounding mode. Fix it up. */ itv.it_value.tv_sec++; itv.it_value.tv_usec -= 1000000; } while (itv.it_value.tv_usec < 0) { /* Likewise. */ itv.it_value.tv_sec--; itv.it_value.tv_usec += 1000000; } /* If the timer looks bad, just spin. */ if (itv.it_value.tv_sec < 0 || /* Another sanity check on FP behaviour */ (itv.it_value.tv_sec == 0 && itv.it_value.tv_usec < 100)) { /* Avoid stupidly short timers */ n = now(); goto retry; } setitimer(ITIMER_PROF, &itv, NULL); }
static void set_ptimer_ticks( mtimer_t *t, int ticks ) { ullong mark = get_mticks_() + ticks; t->tbu = mark >> 32; t->tbl = mark; t->period = ticks; insert_timer( t ); }
void Timer::schedule(void) { assert(!inserted); assert(nextDue != 0); suspend_timers(); insert_timer(this); run_timer_event(); resume_timers(); }
/***************************************************************************** * ddekit_add_timer * ****************************************************************************/ int ddekit_add_timer (void (*fn)(void *), void *args, unsigned long timeout) { struct ddekit_timer_s *t; t = (struct ddekit_timer_s *) ddekit_simple_malloc(sizeof(struct ddekit_timer_s )); t->fn = fn; t->args = args; t->exp = (myclock_t) timeout; return insert_timer(t); }
int resume_ptimer( int id ) { mtimer_t *t; int lost=0; LOCK; if( !(t=dequeue_timer(&ts.inactive, id)) ) printm("resume_ptimer: bogus timer\n"); else { lost = recalc_ptimer( t ); insert_timer( t ); } UNLOCK; return lost; }
static int abs_timer( uint tbu, uint tbl, timer_func_t *handler, void *usr ) { mtimer_t *t; int id=0; LOCK; if( (t=new_timer(handler, usr, 0)) ) { id = t->id; t->tbu = tbu; t->tbl = tbl; insert_timer( t ); } UNLOCK; return id; }
static int rvec_timer( int dummy ) { timer_func_t *handler; mtimer_t *t; void *usr; int id, info; LOCK; while( (t=ts.head) ) { info = get_tbl() - t->tbl; if( info < 0 || (t->flags & TF_OVERFLOW) ) break; /* printm("Latency: %d\n", info ); */ handler= t->handler; usr = t->usr; id = t->id; ts.head = t->next; if( t->flags & TF_PERIODIC ) { if( t->flags & TF_AUTORESUME ) { info = recalc_ptimer( t ); insert_timer( t ); } else { t->next = ts.inactive; ts.inactive = t; } } else { t->next = ts.free; ts.free = t; } UNLOCK; /* info is either latency or lost ticks */ (*handler)( id, usr, info ); LOCK; } mregs->timer_stamp = t->tbl; __recalc_timer = 0; UNLOCK; /* flag a kernel recalculation of mol-DEC */ mregs->flag_bits |= fb_RecalcDecInt; return 0; }
int iu_adjust_timer(iu_tq_t *tq, iu_timer_id_t timer_id, uint32_t sec) { iu_timer_node_t *node; if (timer_id == -1) return (0); for (node = tq->iutq_head; node != NULL; node = node->iutn_next) { if (node->iutn_timer_id == timer_id) { remove_timer(tq, node); insert_timer(tq, node, sec * MILLISEC); return (1); } } return (0); }
/* * iu_schedule_ms_timer(): creates and inserts a timer in the tq's timer list, * using millisecond granularity * * input: iu_tq_t *: the timer queue * uint64_t: the number of milliseconds before this timer fires * iu_tq_callback_t *: the function to call when the timer fires * void *: an argument to pass to the called back function * output: iu_timer_id_t: the new timer's timer id on success, -1 on failure */ iu_timer_id_t iu_schedule_timer_ms(iu_tq_t *tq, uint64_t ms, iu_tq_callback_t *callback, void *arg) { iu_timer_node_t *node = calloc(1, sizeof (iu_timer_node_t)); if (node == NULL) return (-1); node->iutn_callback = callback; node->iutn_arg = arg; node->iutn_timer_id = get_timer_id(tq); if (node->iutn_timer_id == -1) { free(node); return (-1); } insert_timer(tq, node, ms); return (node->iutn_timer_id); }
void erts_set_timer(ErlTimer* p, ErlTimeoutProc timeout, ErlCancelProc cancel, void* arg, Uint t) { erts_deliver_time(); erts_smp_mtx_lock(&tiw_lock); if (p->active) { /* XXX assert ? */ erts_smp_mtx_unlock(&tiw_lock); return; } p->timeout = timeout; p->cancel = cancel; p->arg = arg; p->active = 1; insert_timer(p, t); erts_smp_mtx_unlock(&tiw_lock); #if defined(ERTS_SMP) if (t <= (Uint) ERTS_SHORT_TIME_T_MAX) erts_sys_schedule_interrupt_timed(1, (erts_short_time_t) t); #endif }
static void overflow_handler( int id, void *dummy, int lost_ticks ) { mtimer_t *t, **tp, *chain = NULL; LOCK; for( tp=&ts.head; (t=*tp) ; ) { if( !(t->flags & TF_OVERFLOW) ) { tp = &t->next; } else { *tp = t->next; t->next = chain; chain = t; } } while( (t=chain) ) { t->flags &= ~TF_OVERFLOW; chain = t->next; insert_timer( t ); } UNLOCK; }
void set_ptimer( int id, uint uperiod ) { mtimer_t *t; if( uperiod <= 10 ) { printm("uperiod too small\n"); uperiod = 2000; } LOCK; if( !(t=dequeue_timer(&ts.inactive, id)) && !(t=dequeue_timer(&ts.head, id)) ) printm("bogus timer\n"); else { ullong mark = usecs_to_mticks_( uperiod ); t->period = mark; mark += get_mticks_(); t->tbu = mark >> 32; t->tbl = mark; insert_timer( t ); } UNLOCK; }
int main(int argc, char **argv) { const char *b, *e, *p; const char *output_file = NULL; int f, tot, last, linenum, err, parse_err; struct timer *t = NULL, *t2; struct eb32_node *n; int val, test; int array[5]; int filter_acc_delay = 0, filter_acc_count = 0; int filter_time_resp = 0; int skip_fields = 1; argc--; argv++; while (argc > 0) { if (*argv[0] != '-') break; if (strcmp(argv[0], "-ad") == 0) { if (argc < 2) die("missing option for -ad"); argc--; argv++; filter |= FILT_ACC_DELAY; filter_acc_delay = atol(*argv); } else if (strcmp(argv[0], "-ac") == 0) { if (argc < 2) die("missing option for -ac"); argc--; argv++; filter |= FILT_ACC_COUNT; filter_acc_count = atol(*argv); } else if (strcmp(argv[0], "-rt") == 0) { if (argc < 2) die("missing option for -rt"); argc--; argv++; filter |= FILT_TIME_RESP; filter_time_resp = atol(*argv); } else if (strcmp(argv[0], "-RT") == 0) { if (argc < 2) die("missing option for -RT"); argc--; argv++; filter |= FILT_TIME_RESP | FILT_INVERT_TIME_RESP; filter_time_resp = atol(*argv); } else if (strcmp(argv[0], "-s") == 0) { if (argc < 2) die("missing option for -s"); argc--; argv++; skip_fields = atol(*argv); } else if (strcmp(argv[0], "-e") == 0) filter |= FILT_ERRORS_ONLY; else if (strcmp(argv[0], "-E") == 0) filter |= FILT_ERRORS_ONLY | FILT_INVERT_ERRORS; else if (strcmp(argv[0], "-c") == 0) filter |= FILT_COUNT_ONLY; else if (strcmp(argv[0], "-q") == 0) filter |= FILT_QUIET; else if (strcmp(argv[0], "-v") == 0) filter_invert = !filter_invert; else if (strcmp(argv[0], "-gt") == 0) filter |= FILT_GRAPH_TIMERS; else if (strcmp(argv[0], "-pct") == 0) filter |= FILT_PERCENTILE; else if (strcmp(argv[0], "-o") == 0) { if (output_file) die("Fatal: output file name already specified.\n"); if (argc < 2) die("Fatal: missing output file name.\n"); output_file = argv[1]; } argc--; argv++; } if (!filter) die("No action specified.\n"); if (filter & FILT_ACC_COUNT && !filter_acc_count) filter_acc_count=1; if (filter & FILT_ACC_DELAY && !filter_acc_delay) filter_acc_delay = 1; linenum = 0; tot = 0; parse_err = 0; while ((line = fgets2(stdin)) != NULL) { linenum++; test = 1; if (filter & FILT_TIME_RESP) { int tps; /* only report lines with response times larger than filter_time_resp */ b = field_start(line, TIME_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } e = field_stop(b + 1); /* we have field TIME_FIELD in [b]..[e-1] */ p = b; err = 0; for (f = 0; f < 4 && *p; f++) { tps = str2ic(p); if (tps < 0) { tps = -1; err = 1; } SKIP_CHAR(p, '/'); } if (f < 4) { parse_err++; continue; } test &= (tps >= filter_time_resp) ^ !!(filter & FILT_INVERT_TIME_RESP); } if (filter & FILT_ERRORS_ONLY) { /* only report erroneous status codes */ b = field_start(line, STATUS_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } if (*b == '-') { test &= !!(filter & FILT_INVERT_ERRORS); } else { val = strl2ui(b, 3); test &= (val >= 500 && val <= 599) ^ !!(filter & FILT_INVERT_ERRORS); } } if (filter & (FILT_ACC_COUNT|FILT_ACC_DELAY)) { b = field_start(line, ACCEPT_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } tot++; val = convert_date(b); //printf("date=%s => %d\n", b, val); if (val < 0) { parse_err++; continue; } t2 = insert_value(&timers[0], &t, val); t2->count++; continue; } if (filter & (FILT_GRAPH_TIMERS|FILT_PERCENTILE)) { int f; b = field_start(line, TIME_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } e = field_stop(b + 1); /* we have field TIME_FIELD in [b]..[e-1] */ p = b; err = 0; for (f = 0; f < 5 && *p; f++) { array[f] = str2ic(p); if (array[f] < 0) { array[f] = -1; err = 1; } SKIP_CHAR(p, '/'); } if (f < 5) { parse_err++; continue; } /* if we find at least one negative time, we count one error * with a time equal to the total session time. This will * emphasize quantum timing effects associated to known * timeouts. Note that on some buggy machines, it is possible * that the total time is negative, hence the reason to reset * it. */ if (filter & FILT_GRAPH_TIMERS) { if (err) { if (array[4] < 0) array[4] = -1; t2 = insert_timer(&timers[0], &t, array[4]); // total time t2->count++; } else { int v; t2 = insert_timer(&timers[1], &t, array[0]); t2->count++; // req t2 = insert_timer(&timers[2], &t, array[2]); t2->count++; // conn t2 = insert_timer(&timers[3], &t, array[3]); t2->count++; // resp v = array[4] - array[0] - array[1] - array[2] - array[3]; // data time if (v < 0 && !(filter & FILT_QUIET)) fprintf(stderr, "ERR: %s (%d %d %d %d %d => %d)\n", line, array[0], array[1], array[2], array[3], array[4], v); t2 = insert_timer(&timers[4], &t, v); t2->count++; tot++; } } else { /* percentile */ if (err) { if (array[4] < 0) array[4] = -1; t2 = insert_value(&timers[0], &t, array[4]); // total time t2->count++; } else { int v; t2 = insert_value(&timers[1], &t, array[0]); t2->count++; // req t2 = insert_value(&timers[2], &t, array[2]); t2->count++; // conn t2 = insert_value(&timers[3], &t, array[3]); t2->count++; // resp v = array[4] - array[0] - array[1] - array[2] - array[3]; // data time if (v < 0 && !(filter & FILT_QUIET)) fprintf(stderr, "ERR: %s (%d %d %d %d %d => %d)\n", line, array[0], array[1], array[2], array[3], array[4], v); t2 = insert_value(&timers[4], &t, v); t2->count++; tot++; } } continue; } test ^= filter_invert; if (!test) continue; /* all other cases mean we just want to count lines */ tot++; if (!(filter & FILT_COUNT_ONLY)) puts(line); } if (t) free(t); if (filter & FILT_COUNT_ONLY) { printf("%d\n", tot); exit(0); } if (filter & FILT_ERRORS_ONLY) exit(0); if (filter & (FILT_ACC_COUNT|FILT_ACC_DELAY)) { /* sort and count all timers. Output will look like this : * <accept_date> <delta_ms from previous one> <nb entries> */ n = eb32_first(&timers[0]); if (n) last = n->key; while (n) { unsigned int d, h, m, s, ms; t = container_of(n, struct timer, node); h = n->key; d = h - last; last = h; if (d >= filter_acc_delay && t->count >= filter_acc_count) { ms = h % 1000; h = h / 1000; s = h % 60; h = h / 60; m = h % 60; h = h / 60; tot++; printf("%02d:%02d:%02d.%03d %d %d %d\n", h, m, s, ms, last, d, t->count); } n = eb32_next(n); } }