Esempio n. 1
0
/** @internal Block until wait object is signaled or timeout.
 *
 * This function waits for wait objects and the timers associated with
 * the root object.  When any wait object is signaled or timer is
 * expired, it invokes the callbacks.
 *
 *   This function returns when a callback has been invoked or @c tout
 *   milliseconds is elapsed.
 *
 * @param self     pointer to port
 * @param tout     timeout in milliseconds
 *
 * @return
 *   Milliseconds to the next invocation of timer, or @c SU_WAIT_FOREVER if
 *   there are no active timers.
 */
su_duration_t su_base_port_step(su_port_t *self, su_duration_t tout)
{
  su_time_t now = su_now();

  assert(su_port_own_thread(self));

  if (self->sup_prepoll)
    self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root);

  if (self->sup_head)
    self->sup_vtable->su_port_getmsgs(self);

  if (self->sup_timers)
    su_timer_expire(&self->sup_timers, &tout, now);

  /* XXX: why isn't the timeout ignored here? */
  if (self->sup_deferrable)
    su_timer_expire(&self->sup_deferrable, &tout, now);

  /* if there are messages do a quick wait */
  if (self->sup_head)
    tout = 0;

  if (self->sup_vtable->su_port_wait_events(self, tout))
    tout = 0;
  else
    tout = SU_WAIT_FOREVER;

  if (self->sup_head) {
    if (self->sup_vtable->su_port_getmsgs(self)) {
      /* Check for wait events that may have been generated by messages */
      if (self->sup_vtable->su_port_wait_events(self, 0))
	tout = 0;
    }
  }

  if (self->sup_timers || self->sup_deferrable) {
    su_duration_t tout2 = SU_WAIT_FOREVER;

    now = su_now();
    su_timer_expire(&self->sup_timers, &tout, now);
    su_timer_expire(&self->sup_deferrable, &tout2, now);

    if (tout == SU_WAIT_FOREVER && tout2 != SU_WAIT_FOREVER) {
      if (tout2 < self->sup_max_defer)
	tout2 = self->sup_max_defer;
      tout = tout2;
    }
  }

  if (self->sup_head)
    tout = 0;

  return tout;
}
Esempio n. 2
0
/* This version can help tuning... */
void su_base_port_run_tune(su_port_t *self)
{
  int i;
  int timers = 0, messages = 0, events = 0;
  su_duration_t tout = 0, tout2 = 0;
  su_time_t started = su_now(), woken = started, bedtime = woken;

  assert(su_port_own_thread(self));

  for (self->sup_running = 1; self->sup_running;) {
    tout = self->sup_max_defer;

    timers = 0, messages = 0;

    if (self->sup_prepoll)
      self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root);

    if (self->sup_head)
      messages = self->sup_vtable->su_port_getmsgs(self);

    if (self->sup_timers || self->sup_deferrable) {
      su_time_t now = su_now();
      timers =
	su_timer_expire(&self->sup_timers, &tout, now) +
	su_timer_expire(&self->sup_deferrable, &tout2, now);
    }

    if (!self->sup_running)
      break;

    if (self->sup_head)      /* if there are messages do a quick wait */
      tout = 0;

    bedtime = su_now();

    events = self->sup_vtable->su_port_wait_events(self, tout);

    woken = su_now();

    if (messages || timers || events)
      SU_DEBUG_1(("su_port_run(%p): %.6f: %u messages %u timers %u "
		  "events slept %.6f/%.3f\n",
		  self, su_time_diff(woken, started), messages, timers, events,
		  su_time_diff(woken, bedtime), tout * 1e-3));

    if (!self->sup_running)
      break;
  }
}
Esempio n. 3
0
/** Dump the data from the iovec */
void tport_dump_iovec(tport_t const *self, msg_t *msg,
		      size_t n, su_iovec_t const iov[], size_t iovused,
		      char const *what, char const *how)
{
  tport_master_t *mr;
  char stamp[128];
  size_t i;

  assert(self); assert(msg);

  mr = self->tp_master;
  if (!mr->mr_dump_file)
    return;

  tport_stamp(self, msg, stamp, what, n, how, su_now());
  fputs(stamp, mr->mr_dump_file);

  for (i = 0; i < iovused && n > 0; i++) {
    size_t len = iov[i].mv_len;
    if (len > n)
      len = n;
    if (fwrite(iov[i].mv_base, len, 1, mr->mr_dump_file) != len)
      break;
    n -= len;
  }

  fputs("\v\n", mr->mr_dump_file);
  fflush(mr->mr_dump_file);
}
Esempio n. 4
0
/** @internal Main loop.
 *
 * The function @c su_port_run() waits for wait objects and the timers
 * associated with the port object.  When any wait object is signaled or
 * timer is expired, it invokes the callbacks, and returns waiting.
 *
 * The function @c su_port_run() runs until @c su_port_break() is called
 * from a callback.
 *
 * @param self     pointer to port object
 *
 */
void su_base_port_run(su_port_t *self)
{
  su_duration_t tout = 0, tout2 = 0;

  assert(su_port_own_thread(self));

  for (self->sup_running = 1; self->sup_running;) {
    tout = self->sup_max_defer;

    if (self->sup_prepoll)
      self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root);

    if (self->sup_head)
      self->sup_vtable->su_port_getmsgs(self);

    if (self->sup_timers || self->sup_deferrable) {
      su_time_t now = su_now();
      su_timer_expire(&self->sup_timers, &tout, now);
      su_timer_expire(&self->sup_deferrable, &tout2, now);
    }

    if (!self->sup_running)
      break;

    if (self->sup_head)      /* if there are messages do a quick wait */
      tout = 0;

    self->sup_vtable->su_port_wait_events(self, tout);
  }
}
Esempio n. 5
0
/** Get current timestamp in milliseconds */
su_inline
uint32_t server_now(server_t const *srv)
{
  if (srv->srv_now)
    return srv->srv_now;
  else
    return su_time_ms(su_now());
}
Esempio n. 6
0
/** Get current timestamp in milliseconds */
static
uint32_t he_now(nth_engine_t const *he)
{
  if (he->he_now)
    return he->he_now;
  else
    return su_time_ms(su_now());
}
Esempio n. 7
0
/**Run event and message loop for given duration.
 *
 * The function su_root_sleep() runs event loop for @a duration milliseconds.
 * The event loop waits for wait objects and the timers associated with the
 * @a root object.  When any wait object is signaled, timer is expired, or
 * message is received, it invokes the callbacks and returns waiting.
 *
 * @param self      pointer to root object
 * @param duration  milliseconds to run event loop
 *
 * @retval milliseconds until next timer expiration
 */
su_duration_t su_root_sleep(su_root_t *self, su_duration_t duration)
{
    su_duration_t retval, accrued = 0;
    su_time_t started;

    if (self == NULL)
        return (void)(errno = EFAULT), SU_WAIT_FOREVER;

    assert(self->sur_port);
    started = su_now();

    do {
        retval = su_port_step(self->sur_port, duration - accrued);
        accrued = su_duration(su_now(), started);
    } while (accrued < duration);

    return retval;
}
Esempio n. 8
0
/**
 * Server timer routine.
 */
static
void server_timer(su_root_magic_t *rm, su_timer_t *timer, server_t *srv)
{
  uint32_t now;

  su_timer_set(timer, server_timer, srv);

  now = su_time_ms(su_now()); now += now == 0; srv->srv_now = now;

  /* Xyzzy */

  srv->srv_now = 0;
}
void
print_stamp(struct tester *x, su_timer_t *t, struct timing *ti)
{
  su_time_t now = su_now(), prev = ti->t_prev;

  ti->t_prev = now;

  printf("timer interval %f\n", 1000 * su_time_diff(now, prev));

  if (!ti->t_run)
    su_timer_set(t, print_stamp, ti);

  if (++ti->t_times >= 10)
    su_timer_reset(t);
}
Esempio n. 10
0
/**
 * Engine timer routine.
 */
static
void he_timer(su_root_magic_t *rm, su_timer_t *timer, nth_engine_t * he)
{
  unsigned i;
  uint32_t now;
  hc_htable_t *hct = he->he_clients;

  now = su_time_ms(su_now());
  now += now == 0;
  he->he_now = now;

  if (hct)
    for (i = hct->hct_size; i > 0;)
      if (hct->hct_table[--i])
	hc_timer(he, hct->hct_table[i], now);

  su_timer_set(timer, he_timer, he);

  he->he_now = 0;
}
/*
 * test su_timer functionality:
 *
 * Create a timer, executing print_stamp() in every 20 ms
 */
int main(int argc, char *argv[])
{
  su_root_t *root;
  su_timer_t *t, *t1, *t_end;
  su_timer_t **timers;
  su_duration_t interval = 60;
  char *argv0 = argv[0];
  char *s;
  int use_t1 = 0;
  su_time_t now, started;
  intptr_t i, N = 500;
  GSource *source;

  struct timing timing[1] = {{ 0 }};
  struct tester tester[1] = {{ 0 }};

  while (argv[1] && argv[1][0] == '-') {
    char *o = argv[1] + 1;
    while (*o) {
      if (*o == '1')
	o++, use_t1 = 1;
      else if (*o == 'r')
	o++, timing->t_run = 1;
      else if (*o == 'N') {
	if (o[1])
	  N = strtoul(o + 1, &o, 0);
	else if (argv[2])
	  N = strtoul(argv++[2], &o, 0);
	break;
      }
      else
	break;

    }
    if (*o)
      usage(argv0);
    argv++;
  }

  if (argv[1]) {
    interval = strtoul(argv[1], &s, 10);

    if (interval == 0 || s == argv[1])
      usage(argv0);
  }

  su_init(); atexit(su_deinit);

  tester->root = root = su_glib_root_create(tester);

  source = su_root_gsource(tester->root);
  g_source_attach(source, NULL /*g_main_context_default ()*/);

  su_msg_create(intr_msg,
		su_root_task(root),
		su_root_task(root),
		test_break, 0);

  signal(SIGINT, intr_handler);
#if HAVE_SIGPIPE
  signal(SIGPIPE, intr_handler);
  signal(SIGQUIT, intr_handler);
  signal(SIGHUP, intr_handler);
#endif

  t = su_timer_create(su_root_task(root), interval);
  t1 = su_timer_create(su_root_task(root), 1);
  t_end = su_timer_create(su_root_task(root), 20 * interval);

  if (t == NULL || t1 == NULL || t_end == NULL)
    su_perror("su_timer_create"), exit(1);

  tester->t = t, tester->t1 = t1;

  timing->t_prev = su_now();

  if (timing->t_run)
    su_timer_run(t, print_stamp, timing);
  else
    su_timer_set(t, print_stamp, timing);

  if (use_t1)
    su_timer_set(t1, print_X, NULL);

  su_timer_set(t_end, end_test, NULL);

  su_root_run(root);

  su_msg_destroy(intr_msg);

  su_timer_destroy(t);
  su_timer_destroy(t1);

  if (timing->t_times != 10) {
    fprintf(stderr, "%s: t expired %d times (expecting 10)\n",
	    argv0, timing->t_times);
    return 1;
  }

  /* Insert timers in order */
  timers = calloc(N, sizeof *timers);
  if (!timers) { perror("calloc"); exit(1); }

  now = started = su_now();

  for (i = 0; i < N; i++) {
    t = su_timer_create(su_root_task(root), 1000);
    if (!t) { perror("su_timer_create"); exit(1); }
    if (++now.tv_usec == 0) ++now.tv_sec;
    su_timer_set_at(t, increment, (void *)i, now);
    timers[i] = t;
  }

  tester->sentinel = (void*)(i - 1);

  su_root_run(root);

  printf("Processing %u timers took %f millisec (%f expected)\n",
	 (unsigned)i, su_time_diff(su_now(), started) * 1000, (double)i / 1000);

  for (i = 0; i < N; i++) {
    su_timer_destroy(timers[i]);
  }

  su_root_destroy(root);

  su_deinit();

  return 0;
}
Esempio n. 12
0
 TimerEventHandle TimerQueue::add( TimerFunc f, void* functionArgs, uint32_t milliseconds ) {
   return add( f, functionArgs, milliseconds, su_now() ) ;
 }
Esempio n. 13
0
  void TimerQueue::doTimer(su_timer_t* timer) {
    //self check
    assert( m_length == numberOfElements()) ;
    assert( 0 != m_length || (NULL == m_head && NULL == m_tail) ) ;
    assert( 1 != m_length || (m_head == m_tail)) ;
    assert( m_length < 2 || (m_head != m_tail)) ;
    assert( !(NULL == m_head && NULL != m_tail)) ;
    assert( !(NULL == m_tail && NULL != m_head)) ;

#ifndef TEST
    DR_LOG(log_debug) << m_name << ": running timer function" ;
#endif
    //std::cout << "doTimer: running timer function with " << m_length << " timers queued " << std::endl;

    if( m_in_timer ) return ;
    m_in_timer = 1 ;

    queueEntry_t* expired = NULL ;
    queueEntry_t* tailExpired = NULL ;

    su_time_t now = su_now() ;
    assert( NULL != m_head ) ;

    queueEntry_t* ptr = m_head ;
    while( ptr && su_time_cmp( ptr->m_when, now ) < 0 ) {
      //std::cout << "expiring a timer" << std::endl ;
      m_length-- ;
      m_head = ptr->m_next ;
      if( m_head ) m_head->m_prev = NULL ;
      else m_tail = NULL ;

      //detach and assemble them into a new queue temporarily
      if( !expired ) {
        expired = tailExpired = ptr ;
        ptr->m_prev = ptr->m_next = NULL ;
      }
      else {
        tailExpired->m_next = ptr ;
        ptr->m_prev = tailExpired ;
        tailExpired = ptr ;
      }
      ptr = ptr->m_next ;
    }

    if( NULL == m_head ) {
#ifndef TEST
      DR_LOG(log_debug) << m_name << ": timer not set (queue is empty after processing expired timers), length: " << dec << m_length ;
#endif
      //std::cout << "doTimer: timer not set (queue is empty after processing expired timers)" << std::endl;
      assert( 0 == m_length ) ;
    }
    else {
      //std::cout << "doTimer: Setting timer for " << su_duration( m_head->m_when, su_now() )  << "ms after processing expired timers" << std::endl;
#ifndef TEST
      DR_LOG(log_debug) << m_name << ": Setting timer for " << su_duration( m_head->m_when, su_now() )  << 
        "ms after processing expired timers, length: "  << dec << m_length ;
#endif
      int rc = su_timer_set_at(m_timer, timer_function, this, m_head->m_when);      
    }
    m_in_timer = 0 ;

    while( NULL != expired ) {
      expired->m_function( expired->m_functionArgs ) ;
      queueEntry_t* p = expired ;
      expired = expired->m_next ;
      delete p ;
    }    

    //self check
    assert( m_length == numberOfElements()) ;
    assert( 0 != m_length || (NULL == m_head && NULL == m_tail) ) ;
    assert( 1 != m_length || (m_head == m_tail)) ;
    assert( m_length < 2 || (m_head != m_tail)) ;
    assert( !(NULL == m_head && NULL != m_tail)) ;
    assert( !(NULL == m_tail && NULL != m_head)) ;
  }    
Esempio n. 14
0
  void TimerQueue::remove( TimerEventHandle entry) {
#ifndef TEST
        DR_LOG(log_debug) << m_name << ": removing entry, prior to removal length: " << dec << m_length;
#endif
    //self check
    assert( m_length == numberOfElements()) ;
    assert( 0 != m_length || (NULL == m_head && NULL == m_tail) ) ;
    assert( 1 != m_length || (m_head == m_tail)) ;
    assert( m_length < 2 || (m_head != m_tail)) ;
    assert( !(NULL == m_head && NULL != m_tail)) ;
    assert( !(NULL == m_tail && NULL != m_head)) ;
    assert( m_head && m_length >= 1 ) ;

    int queueLength ;
    {
      if( m_head == entry ) {
        m_head = entry->m_next ;
        if( m_head ) m_head->m_prev = NULL ;
        else {
          assert( 1 == m_length ) ;
          m_tail = NULL ;
        }
      }
      else if( m_tail == entry ) {
        assert( m_head && entry->m_prev ) ;
        m_tail = entry->m_prev ;
        m_tail->m_next = NULL ;
      }
      else {
        assert( entry->m_prev ) ;
        assert( entry->m_next ) ;
        entry->m_prev->m_next = entry->m_next ;
        entry->m_next->m_prev = entry->m_prev ;
      }
      m_length-- ;
      assert( m_length >= 0 ) ;

      if( NULL == m_head ) {
#ifndef TEST
        DR_LOG(log_debug) << m_name << ": removed entry, timer not set (queue is empty after removal), length: " << dec << m_length;
#endif
        //std::cout << "timer not set (queue is empty after removal)"  << std::endl;
        su_timer_reset( m_timer ) ;
      }
      else if( m_head == entry->m_next ) {
#ifndef TEST
        DR_LOG(log_debug) << m_name << ": removed entry, setting timer for " << std::dec << su_duration( m_head->m_when, su_now() )  << 
          "ms after removal, length: " << dec << m_length;
#endif
        //std::cout << "Setting timer for " << su_duration( m_head->m_when, su_now() )  << "ms after removal of head entry"  << std::endl;
        int rc = su_timer_set_at(m_timer, timer_function, this, m_head->m_when);
      }      
    }

    //DR_LOG(log_debug) << "timer remove: queue length is now " << queueLength ;
    //std::cout << "timer remove: queue length is now " << queueLength << std::endl;

    delete entry ;

    //self check
    assert( m_length == numberOfElements()) ;
    assert( 0 != m_length || (NULL == m_head && NULL == m_tail) ) ;
    assert( 1 != m_length || (m_head == m_tail)) ;
    assert( m_length < 2 || (m_head != m_tail)) ;
    assert( !(NULL == m_head && NULL != m_tail)) ;
    assert( !(NULL == m_tail && NULL != m_head)) ;
  }