static void sctp_handle_tick(int delta) { sctp_os_timer_t *c; void (*c_func)(void *); void *c_arg; SCTP_TIMERQ_LOCK(); /* update our tick count */ ticks += delta; c = TAILQ_FIRST(&SCTP_BASE_INFO(callqueue)); while (c) { if (c->c_time <= ticks) { sctp_os_timer_next = TAILQ_NEXT(c, tqe); TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe); c_func = c->c_func; c_arg = c->c_arg; c->c_flags &= ~SCTP_CALLOUT_PENDING; SCTP_TIMERQ_UNLOCK(); c_func(c_arg); SCTP_TIMERQ_LOCK(); c = sctp_os_timer_next; } else { c = TAILQ_NEXT(c, tqe); } } sctp_os_timer_next = NULL; SCTP_TIMERQ_UNLOCK(); }
void *user_sctp_timer_iterate(void * threadname) { sctp_os_timer_t *c; void (*c_func)(void *); void *c_arg; sctp_os_timer_t *sctp_os_timer_next = NULL; /* * The MSEC_TO_TICKS conversion depends on hz. The to_ticks in * sctp_os_timer_start also depends on hz. E.g. if hz=1000 then * for multiple INIT the to_ticks is 2000, 4000, 8000, 16000, 32000, 60000 * and further to_ticks level off at 60000 i.e. 60 seconds. * If hz=100 then for multiple INIT the to_ticks are 200, 400, 800 and so-on. */ int time_to_ticks = MSEC_TO_TICKS(TIMEOUT_INTERVAL); __suseconds_t timeout_interval = TIMEOUT_INTERVAL * 1000; /* in microseconds */ struct timeval timeout; struct timeval *timeout_ptr; fd_set read_fds; int fd = 23; /* what should this value be? */ FD_ZERO(&read_fds); FD_SET(fd, &read_fds); while(1) { timeout.tv_sec = 0; timeout.tv_usec = timeout_interval; timeout_ptr = &timeout; select(FD_SIZE, &read_fds, NULL, NULL, timeout_ptr); /* update our tick count */ uticks += time_to_ticks; SCTP_TIMERQ_LOCK(); c = TAILQ_FIRST(&SCTP_BASE_INFO(callqueue)); while (c) { if (c->c_time <= uticks) { sctp_os_timer_next = TAILQ_NEXT(c, tqe); TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe); c_func = c->c_func; c_arg = c->c_arg; c->c_flags &= ~SCTP_CALLOUT_PENDING; SCTP_TIMERQ_UNLOCK(); c_func(c_arg); SCTP_TIMERQ_LOCK(); c = sctp_os_timer_next; } else { c = TAILQ_NEXT(c, tqe); } } SCTP_TIMERQ_UNLOCK(); } return NULL; }
void sctp_os_timer_start(sctp_os_timer_t *c, int to_ticks, void (*ftn) (void *), void *arg) { /* paranoia */ if ((c == NULL) || (ftn == NULL)) return; SCTP_TIMERQ_LOCK(); /* check to see if we're rescheduling a timer */ if (c->c_flags & SCTP_CALLOUT_PENDING) { if (c == sctp_os_timer_next) { sctp_os_timer_next = TAILQ_NEXT(c, tqe); } TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe); /* * part of the normal "stop a pending callout" process * is to clear the CALLOUT_ACTIVE and CALLOUT_PENDING * flags. We don't bother since we are setting these * below and we still hold the lock. */ } /* * We could unlock/splx here and lock/spl at the TAILQ_INSERT_TAIL, * but there's no point since doing this setup doesn't take much time. */ if (to_ticks <= 0) to_ticks = 1; c->c_arg = arg; c->c_flags = (SCTP_CALLOUT_ACTIVE | SCTP_CALLOUT_PENDING); c->c_func = ftn; c->c_time = ticks + to_ticks; TAILQ_INSERT_TAIL(&SCTP_BASE_INFO(callqueue), c, tqe); SCTP_TIMERQ_UNLOCK(); }
int sctp_os_timer_stop(sctp_os_timer_t *c) { SCTP_TIMERQ_LOCK(); /* * Don't attempt to delete a callout that's not on the queue. */ if (!(c->c_flags & SCTP_CALLOUT_PENDING)) { c->c_flags &= ~SCTP_CALLOUT_ACTIVE; SCTP_TIMERQ_UNLOCK(); return (0); } c->c_flags &= ~(SCTP_CALLOUT_ACTIVE | SCTP_CALLOUT_PENDING); if (c == sctp_os_timer_next) { sctp_os_timer_next = TAILQ_NEXT(c, tqe); } TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe); SCTP_TIMERQ_UNLOCK(); return (1); }