Esempio n. 1
0
struct atimer *
start_atimer (enum atimer_type type, EMACS_TIME timestamp, atimer_callback fn,
	      void *client_data)
{
  struct atimer *t;

  /* Round TIME up to the next full second if we don't have
     itimers.  */
#ifndef HAVE_SETITIMER
  if (EMACS_NSECS (timestamp) != 0
      && EMACS_SECS (timestamp) < TYPE_MAXIMUM (time_t))
    timestamp = make_emacs_time (EMACS_SECS (timestamp) + 1, 0);
#endif /* not HAVE_SETITIMER */

  /* Get an atimer structure from the free-list, or allocate
     a new one.  */
  if (free_atimers)
    {
      t = free_atimers;
      free_atimers = t->next;
    }
  else
    t = xmalloc (sizeof *t);

  /* Fill the atimer structure.  */
  memset (t, 0, sizeof *t);
  t->type = type;
  t->fn = fn;
  t->client_data = client_data;

  block_atimers ();

  /* Compute the timer's expiration time.  */
  switch (type)
    {
    case ATIMER_ABSOLUTE:
      t->expiration = timestamp;
      break;

    case ATIMER_RELATIVE:
      t->expiration = add_emacs_time (current_emacs_time (), timestamp);
      break;

    case ATIMER_CONTINUOUS:
      t->expiration = add_emacs_time (current_emacs_time (), timestamp);
      t->interval = timestamp;
      break;
    }

  /* Insert the timer in the list of active atimers.  */
  schedule_atimer (t);
  unblock_atimers ();

  /* Arrange for a SIGALRM at the time the next atimer is ripe.  */
  set_alarm ();

  return t;
}
Esempio n. 2
0
static void
set_alarm (void)
{
  if (atimers)
    {
#ifdef HAVE_SETITIMER
      struct itimerval it;
#endif
      EMACS_TIME now, interval;

#ifdef HAVE_ITIMERSPEC
      if (alarm_timer_ok)
	{
	  struct itimerspec ispec;
	  ispec.it_value = atimers->expiration;
	  ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0;
	  if (timer_settime (alarm_timer, 0, &ispec, 0) == 0)
	    return;
	}
#endif

      /* Determine interval till the next timer is ripe.
	 Don't set the interval to 0; this disables the timer.  */
      now = current_emacs_time ();
      interval = (EMACS_TIME_LE (atimers->expiration, now)
		  ? make_emacs_time (0, 1000 * 1000)
		  : sub_emacs_time (atimers->expiration, now));

#ifdef HAVE_SETITIMER

      memset (&it, 0, sizeof it);
      it.it_value = make_timeval (interval);
      setitimer (ITIMER_REAL, &it, 0);
#else /* not HAVE_SETITIMER */
      alarm (max (EMACS_SECS (interval), 1));
#endif /* not HAVE_SETITIMER */
    }
}
Esempio n. 3
0
int
xg_select (int fds_lim, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
	   EMACS_TIME *timeout, sigset_t *sigmask)
{
  SELECT_TYPE all_rfds, all_wfds;
  EMACS_TIME tmo, *tmop = timeout;

  GMainContext *context;
  int have_wfds = wfds != NULL;
  GPollFD gfds_buf[128];
  GPollFD *gfds = gfds_buf;
  int gfds_size = sizeof gfds_buf / sizeof *gfds_buf;
  int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1;
  int i, nfds, tmo_in_millisec;
  USE_SAFE_ALLOCA;

  if (! (x_in_use
	 && g_main_context_pending (context = g_main_context_default ())))
    return pselect (fds_lim, rfds, wfds, efds, timeout, sigmask);

  if (rfds) all_rfds = *rfds;
  else FD_ZERO (&all_rfds);
  if (wfds) all_wfds = *wfds;
  else FD_ZERO (&all_wfds);

  n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec,
				 gfds, gfds_size);
  if (gfds_size < n_gfds)
    {
      SAFE_NALLOCA (gfds, sizeof *gfds, n_gfds);
      gfds_size = n_gfds;
      n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec,
				     gfds, gfds_size);
    }

  for (i = 0; i < n_gfds; ++i)
    {
      if (gfds[i].events & G_IO_IN)
        {
          FD_SET (gfds[i].fd, &all_rfds);
          if (gfds[i].fd > max_fds) max_fds = gfds[i].fd;
        }
      if (gfds[i].events & G_IO_OUT)
        {
          FD_SET (gfds[i].fd, &all_wfds);
          if (gfds[i].fd > max_fds) max_fds = gfds[i].fd;
          have_wfds = 1;
        }
    }

  SAFE_FREE ();

  if (tmo_in_millisec >= 0)
    {
      tmo = make_emacs_time (tmo_in_millisec / 1000,
			     1000 * 1000 * (tmo_in_millisec % 1000));
      if (!timeout || EMACS_TIME_LT (tmo, *timeout))
	tmop = &tmo;
    }

  fds_lim = max_fds + 1;
  nfds = pselect (fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL,
		  efds, tmop, sigmask);

  if (nfds < 0)
    retval = nfds;
  else if (nfds > 0)
    {
      for (i = 0; i < fds_lim; ++i)
        {
          if (FD_ISSET (i, &all_rfds))
            {
              if (rfds && FD_ISSET (i, rfds)) ++retval;
              else ++our_fds;
            }
          else if (rfds)
            FD_CLR (i, rfds);

          if (have_wfds && FD_ISSET (i, &all_wfds))
            {
              if (wfds && FD_ISSET (i, wfds)) ++retval;
              else ++our_fds;
            }
          else if (wfds)
            FD_CLR (i, wfds);

          if (efds && FD_ISSET (i, efds))
            ++retval;
        }
    }

  if (our_fds > 0 || (nfds == 0 && tmop == &tmo))
    {

      /* If Gtk+ is in use eventually gtk_main_iteration will be called,
         unless retval is zero.  */
#ifdef USE_GTK
      if (retval == 0)
#endif
        while (g_main_context_pending (context))
          g_main_context_dispatch (context);

      /* To not have to recalculate timeout, return like this.  */
      if (retval == 0)
        {
          retval = -1;
          errno = EINTR;
        }
    }

  return retval;
}