예제 #1
0
void
insert_probe_timer_entry( probe_timer_entry *new_entry ) {
  probe_timer_entry *last_entry = probe_timer_last->data;
  if ( probe_timer_table->next == NULL
       || timespec_le( &(last_entry->expires ), &( new_entry->expires ) ) ) {
    probe_timer_last = insert_after_dlist( probe_timer_last, new_entry );

    goto set_interval_timer;
  }

  dlist_element *dlist;
  probe_timer_entry *entry;
  for ( dlist = probe_timer_table->next; dlist != NULL; dlist = dlist->next ) {
    entry = dlist->data;
    if ( timespec_le( &(entry->expires ), &( new_entry->expires ) ) ) {
      continue;
    }
    insert_before_dlist( dlist, new_entry );
    goto set_interval_timer;
  }
  UNREACHABLE();

set_interval_timer:

  if ( probe_timer_table->next->data != new_entry ) {
    return;
  }

#if 0
  set_interval_timer();
#endif
}
예제 #2
0
static void
interval_timer_event( void *user_data ) {
  UNUSED( user_data );

  struct timespec now;
  dlist_element *dlist, *next;
  probe_timer_entry *entry;
  for ( dlist = probe_timer_table->next; dlist != NULL; dlist = next ) {
    next = dlist->next;
    entry = dlist->data;
    get_current_time( &now );
    if ( timespec_le( &( entry->expires ), &now ) ) {
      if ( dlist == probe_timer_last ) {
        probe_timer_last = dlist->prev;
      }
      delete_dlist_element( dlist );
      probe_request( entry, PROBE_TIMER_EVENT_TIMEOUT, 0, 0 );
    } else {
#if 0
      set_interval_timer();
#endif
      return;
    }
  }
}
예제 #3
0
static inline bool
other_port_status_changed( probe_timer_entry *entry ) {
  if ( entry->link_up ) {
    probe_timer_entry *peer = lookup_probe_timer_entry( &entry->to_datapath_id,
                                                        entry->to_port_no );
    return peer == NULL;
  }
  return !timespec_le( &port_down_time, &( entry->link_down_time ) );
}
예제 #4
0
파일: refresh_file.c 프로젝트: Aconex/pcp
int refresh_file( struct file_state *f_s ){
	struct timespec now, tmp;
	int i = 0;

	if (f_s->datap) {
		/* get time */
		if ( clock_gettime(CLOCK_MONOTONIC, &now) < 0 ) {
			/* if we don't know what time it is */
			/* there's nothing we can do with this */
			return 0;
		}
		/* if time since last refresh > delta */
		tmp = timespec_add( &f_s->ts, &file_time_offset);
		if ( timespec_le( &now, &tmp) ) {
			/* file is recent */
			return 0;
		}
		f_s->ts = now;
		/* clear old data, make errors obvious, autoterm trailing strings */
		memset ( f_s->datap, 0,  f_s->datas );
	}
	/* if fd is null open file */
	if ( f_s->fd <= 0) { 
		if (( f_s->fd = open (f_s->filename, O_RDONLY)) < 0) {
			perror("refresh_file: open");
			return -1;
		}
	}
	if ( lseek (f_s->fd, 0, SEEK_SET) < 0 ) {
		perror("refresh_file: initial seek");
		return -1;
	}
	/* only grow, never shrink... what would be the point? */
	while (f_s->datap && (i = read (f_s->fd, f_s->datap, f_s->datas)) >= f_s->datas ){
		/* oh heck, what do I do if this fails? */
		f_s->datas += BUFFERBLOCK;
                if ((f_s->datap = realloc(f_s->datap,  f_s->datas)) == NULL){
                       free((char *)f_s->datap);
                       perror("refresh_file: realloc");
                       return -1;
                }
		if ( lseek (f_s->fd, 0, SEEK_SET) < 0 ) {
			perror("refresh_file: subsequent seek");
			return -1;
		}
	}
	if (i < 0 ){
		/* read failed */
		perror("refresh_file: file read failed");
		return -1;
	}
	return 0;
}
예제 #5
0
파일: exchange.c 프로젝트: majek/openonload
static void event_loop(struct server_state* ss)
{
  msg(1, "Starting event loop\n");

  struct timespec tx_ts, rx_ts, next_tx_ts, lost_tx_ts = { 0, 0 };
  ss->have_sent = ss->have_tx_ts = ss->have_rx_ts = false;
  int rc, rx_left = ss->rx_msg_size;
  unsigned send_i = 0;

  clock_gettime(CLOCK_REALTIME, &next_tx_ts);
  timespec_add_ns(&next_tx_ts, ss->inter_tx_gap_ns);

  while( 1 ) {
    struct epoll_event e;
    TRY( rc = epoll_wait(ss->epoll, &e, 1, 0) );

    if( rc == 0 ) {
      struct timespec now;
      clock_gettime(CLOCK_REALTIME, &now);
      if( ! timespec_le(next_tx_ts, now) )
        continue;
      timespec_add_ns(&next_tx_ts, ss->inter_tx_gap_ns);
      if( ++send_i >= cfg_measure_nth && ! ss->have_sent ) {
        msg(3, "Send message (timed)\n");
        TEST( send(ss->udp_sock_ts, ss->tx_buf_ts, ss->tx_msg_size, 0)
                == ss->tx_msg_size );
        if( ! cfg_hw_ts ) {
          ss->have_tx_ts = true;
          tx_ts = now;
        }
        send_i = 0;
        ss->have_sent = true;
      }
      else {
        msg(3, "Send message\n");
        TEST( send(ss->udp_sock, ss->tx_buf, ss->tx_msg_size, 0)
                == ss->tx_msg_size );
        if( send_i >= cfg_measure_nth ) {
          /* Not had a reply to last timed message.  Try to detect lost
           * messages.
           */
          if( send_i == cfg_measure_nth ) {
            lost_tx_ts = now;
          }
          else if( ss->have_tx_ts &&
                   timespec_diff_ns(now, lost_tx_ts) > 10000000 ) {
            msg(2, "WARNING: No response to timed message\n");
            if( ss->rtt_n > 0 )
              ++(ss->n_lost_msgs);
            ss->have_sent = false;
            ss->have_tx_ts = false;
            ss->have_rx_ts = false;
          }
        }
      }
    }

    else if( e.data.fd == ss->tcp_sock ) {
      TEST( e.events & EPOLLIN );
      if( cfg_hw_ts ) {
        rc = recv_ts(ss->tcp_sock, ss->rx_buf, rx_left, MSG_DONTWAIT, &rx_ts);
      }
      else {
        rc = recv(ss->tcp_sock, ss->rx_buf, rx_left, MSG_DONTWAIT);
        clock_gettime(CLOCK_REALTIME, &rx_ts);
      }
      if( rc > 0 ) {
        msg(3, "Received %d from client at %d.%09d\n", rc,
            (int) rx_ts.tv_sec, (int) rx_ts.tv_nsec);
        if( (rx_left -= rc) == 0 ) {
          send(ss->tcp_sock, ss->rx_buf, 1, MSG_NOSIGNAL);
          rx_left = ss->rx_msg_size;
          ss->have_rx_ts = true;
          if( ss->have_tx_ts )
            measured_rtt(ss, tx_ts, rx_ts);
        }
      }
      else if( rc == 0 || errno == ECONNRESET ) {
        break;
      }
      else if( errno == ETIME ) {
        fprintf(stderr, "ERROR: Did not get H/W timestamp on RX\n");
        exit(3);
      }
      else {
        TRY( rc );
      }
    }

    else if( e.data.fd == ss->udp_sock_ts ) {
      assert( cfg_hw_ts );
      assert( ! ss->have_tx_ts );
      TEST( recv_ts(ss->udp_sock_ts, ss->rx_buf, 1,
                    MSG_ERRQUEUE | MSG_DONTWAIT, &tx_ts) == 1 );
      msg(3, "TX timestamp %d.%09d\n", (int) tx_ts.tv_sec,
             (int) tx_ts.tv_nsec);
      ss->have_tx_ts = true;
      if( ss->have_rx_ts )
        measured_rtt(ss, tx_ts, rx_ts);
    }
  }

  msg(1, "Client disconnected\n");
  TRY( close(ss->tcp_sock) );
}
예제 #6
0
int sys_ppoll(struct pollfd* user_fds, size_t nfds,
              const struct timespec* user_timeout_ts,
              const sigset_t* user_sigmask)
{
	ioctx_t ctx; SetupKernelIOCtx(&ctx);

	struct timespec timeout_ts;
	if ( !FetchTimespec(&timeout_ts, user_timeout_ts) )
		return -1;

	if ( user_sigmask )
		return errno = ENOSYS, -1;

	struct pollfd* fds = CopyFdsFromUser(user_fds, nfds);
	if ( !fds ) { return -1; }

	PollNode* nodes = new PollNode[nfds];
	if ( !nodes ) { delete[] fds; return -1; }

	Process* process = CurrentProcess();

	kthread_mutex_t wakeup_mutex = KTHREAD_MUTEX_INITIALIZER;
	kthread_cond_t wakeup_cond = KTHREAD_COND_INITIALIZER;

	kthread_mutex_lock(&wakeup_mutex);

	int ret = -1;
	bool self_woken = false;
	bool remote_woken = false;
	bool unexpected_error = false;

	Timer timer;
	struct poll_timeout pts;
	if ( timespec_le(timespec_make(0, 1), timeout_ts) )
	{
		timer.Attach(Time::GetClock(CLOCK_MONOTONIC));
		struct itimerspec its;
		its.it_interval = timespec_nul();
		its.it_value = timeout_ts;
		pts.wake_mutex = &wakeup_mutex;
		pts.wake_cond = &wakeup_cond;
		pts.woken = &remote_woken;
		timer.Set(&its, NULL, 0, poll_timeout_callback, &pts);
	}

	size_t reqs;
	for ( reqs = 0; !unexpected_error && reqs < nfds; )
	{
		PollNode* node = nodes + reqs;
		if ( fds[reqs].fd < 0 )
		{
			fds[reqs].revents = POLLNVAL;
			// TODO: Should we set POLLNVAL in node->revents too? Should this
			// system call ignore this error and keep polling, or return to
			// user-space immediately? What if conditions are already true on
			// some of the file descriptors (those we have processed so far?)?
			node->revents = 0;
			reqs++;
			continue;
		}
		Ref<Descriptor> desc = process->GetDescriptor(fds[reqs].fd);
		if ( !desc ) { self_woken = unexpected_error = true; break; }
		node->events = fds[reqs].events | POLL__ONLY_REVENTS;
		node->revents = 0;
		node->wake_mutex = &wakeup_mutex;
		node->wake_cond = &wakeup_cond;
		node->woken = &remote_woken;
		reqs++;
		// TODO: How should errors be handled?
		if ( desc->poll(&ctx, node) == 0 )
			self_woken = true;
		else if ( errno == EAGAIN )
			errno = 0;
		else
			unexpected_error = self_woken = true;
	}

	if ( timeout_ts.tv_sec == 0 && timeout_ts.tv_nsec == 0 )
		self_woken = true;

	while ( !(self_woken || remote_woken) )
	{
		if ( !kthread_cond_wait_signal(&wakeup_cond, &wakeup_mutex) )
			errno = -EINTR,
			self_woken = true;
	}

	kthread_mutex_unlock(&wakeup_mutex);

	for ( size_t i = 0; i < reqs; i++ )
		if ( 0 <= fds[i].fd )
			nodes[i].Cancel();

	if ( timespec_le(timespec_make(0, 1), timeout_ts) )
	{
		timer.Cancel();
		timer.Detach();
	}

	if ( !unexpected_error )
	{
		int num_events = 0;
		for ( size_t i = 0; i < reqs; i++ )
		{
			if ( fds[i].fd < -1 )
				continue;
			if ( (fds[i].revents = nodes[i].revents) )
				num_events++;
		}

		if ( CopyFdsToUser(user_fds, fds, nfds) )
			ret = num_events;
	}

	delete[] nodes;
	delete[] fds;
	return ret;
}