コード例 #1
0
static eventer_t eventer_kqueue_impl_remove(eventer_t e) {
  eventer_t removed = NULL;
  if(e->mask & EVENTER_ASYNCH) {
    abort();
  }
  if(e->mask & (EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION)) {
    ev_lock_state_t lockstate;
    lockstate = acquire_master_fd(e->fd);
    noitL(eventer_deb, "kqueue: remove(%d)\n", e->fd);
    if(e == master_fds[e->fd].e) {
      removed = e;
      master_fds[e->fd].e = NULL;
      if(e->mask & (EVENTER_READ | EVENTER_EXCEPTION))
        ke_change(e->fd, EVFILT_READ, EV_DELETE | EV_DISABLE, e);
      if(e->mask & (EVENTER_WRITE))
        ke_change(e->fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, e);
    } else
      noitL(eventer_deb, "kqueue: remove(%d) failed.\n", e->fd);
    release_master_fd(e->fd, lockstate);
  }
  else if(e->mask & EVENTER_TIMER) {
    removed = eventer_remove_timed(e);
  }
  else if(e->mask & EVENTER_RECURRENT) {
    removed = eventer_remove_recurrent(e);
  }
  else {
    abort();
  }
  return removed;
}
コード例 #2
0
static void eventer_kqueue_impl_update(eventer_t e, int mask) {
  if(e->mask & EVENTER_TIMER) {
    eventer_update_timed(e, mask);
    return;
  }
  noitL(eventer_deb, "kqueue: update(%d, %x->%x)\n", e->fd, e->mask, mask);
  /* Disable old, if they aren't active in the new */
  if((e->mask & (EVENTER_READ | EVENTER_EXCEPTION)) &&
     !(mask & (EVENTER_READ | EVENTER_EXCEPTION)))
    ke_change(e->fd, EVFILT_READ, EV_DELETE | EV_DISABLE, e);
  if((e->mask & (EVENTER_WRITE)) &&
     !(mask & (EVENTER_WRITE)))
    ke_change(e->fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, e);

  /* Enable new, if the weren't in the old */
  if((mask & (EVENTER_READ | EVENTER_EXCEPTION)) &&
     !(e->mask & (EVENTER_READ | EVENTER_EXCEPTION)))
    ke_change(e->fd, EVFILT_READ, EV_ADD | EV_ENABLE, e);
  if((mask & (EVENTER_WRITE)) &&
     !(e->mask & (EVENTER_WRITE)))
    ke_change(e->fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, e);

  /* Switch */
  e->mask = mask;
}
コード例 #3
0
static eventer_t eventer_kqueue_impl_remove(eventer_t e) {
  eventer_t removed = NULL;
  if(e->mask & EVENTER_ASYNCH) {
    mtevFatal(mtev_error, "error in eventer_kqueue_impl_remove: got unexpected EVENTER_ASYNCH mask\n");
  }
  if(e->mask & (EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION)) {
    ev_lock_state_t lockstate;
    lockstate = acquire_master_fd(e->fd);
    mtevL(eventer_deb, "kqueue: remove(%d)\n", e->fd);
    if(e == master_fds[e->fd].e) {
      removed = e;
      master_fds[e->fd].e = NULL;
      if(e->mask & (EVENTER_READ | EVENTER_EXCEPTION))
        ke_change(e->fd, EVFILT_READ, EV_DELETE | EV_DISABLE, e);
      if(e->mask & (EVENTER_WRITE))
        ke_change(e->fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, e);
    } else
      mtevL(eventer_deb, "kqueue: remove(%d) failed.\n", e->fd);
    release_master_fd(e->fd, lockstate);
  }
  else if(e->mask & EVENTER_TIMER) {
    removed = eventer_remove_timed(e);
  }
  else if(e->mask & EVENTER_RECURRENT) {
    removed = eventer_remove_recurrent(e);
  }
  else {
    mtevFatal(mtev_error, "error in eventer_kqueue_impl_remove: got unknown mask (0x%04x)\n",
            e->mask);
  }
  return removed;
}
コード例 #4
0
static eventer_t eventer_kqueue_impl_remove_fd(int fd) {
  eventer_t eiq = NULL;
  ev_lock_state_t lockstate;
  if(master_fds[fd].e) {
    noitL(eventer_deb, "kqueue: remove_fd(%d)\n", fd);
    lockstate = acquire_master_fd(fd);
    eiq = master_fds[fd].e;
    master_fds[fd].e = NULL;
    if(eiq->mask & (EVENTER_READ | EVENTER_EXCEPTION))
      ke_change(fd, EVFILT_READ, EV_DELETE | EV_DISABLE, eiq);
    if(eiq->mask & (EVENTER_WRITE))
      ke_change(fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, eiq);
    release_master_fd(fd, lockstate);
  }
  return eiq;
}
コード例 #5
0
static void
alter_kqueue_mask(eventer_t e, int oldmask, int newmask) {
  /* toggle the read bits if needed */
  if(newmask & (EVENTER_READ | EVENTER_EXCEPTION)) {
    if(!(oldmask & (EVENTER_READ | EVENTER_EXCEPTION)))
      ke_change(e->fd, EVFILT_READ, EV_ADD | EV_ENABLE, e);
  }
  else if(oldmask & (EVENTER_READ | EVENTER_EXCEPTION))
    ke_change(e->fd, EVFILT_READ, EV_DELETE | EV_DISABLE, e);

  /* toggle the write bits if needed */
  if(newmask & EVENTER_WRITE) {
    if(!(oldmask & EVENTER_WRITE))
      ke_change(e->fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, e);
  }
  else if(oldmask & EVENTER_WRITE)
    ke_change(e->fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, e);
}
コード例 #6
0
static void eventer_kqueue_impl_add(eventer_t e) {
  mtevAssert(e->mask);
  mtevAssert(eventer_is_loop(e->thr_owner) >= 0);
  ev_lock_state_t lockstate;
  const char *cbname;
  cbname = eventer_name_for_callback_e(e->callback, e);

  if(e->mask & EVENTER_ASYNCH) {
    mtevL(eventer_deb, "debug: eventer_add asynch (%s)\n", cbname ? cbname : "???");
    eventer_add_asynch(NULL, e);
    return;
  }

  /* Recurrent delegation */
  if(e->mask & EVENTER_RECURRENT) {
    mtevL(eventer_deb, "debug: eventer_add recurrent (%s)\n", cbname ? cbname : "???");
    eventer_add_recurrent(e);
    return;
  }

  /* Timed events are simple */
  if(e->mask & EVENTER_TIMER) {
    eventer_add_timed(e);
    return;
  }

  /* file descriptor event */
  mtevL(eventer_deb, "debug: eventer_add fd (%s,%d,0x%04x)\n", cbname ? cbname : "???", e->fd, e->mask);
  mtevAssert(e->whence.tv_sec == 0 && e->whence.tv_usec == 0);
  lockstate = acquire_master_fd(e->fd);
  master_fds[e->fd].e = e;
  if(e->mask & (EVENTER_READ | EVENTER_EXCEPTION))
    ke_change(e->fd, EVFILT_READ, EV_ADD | EV_ENABLE, e);
  if(e->mask & (EVENTER_WRITE))
    ke_change(e->fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, e);
  release_master_fd(e->fd, lockstate);
}
コード例 #7
0
static void
do_accept (register struct kevent const *const kep)
{
  auto sockaddr_in sin;
  auto socklen_t sinsiz;
  register int s;
  register ecb *ecbp;

  if ((s = accept (kep->ident, (struct sockaddr *)&sin, &sinsiz)) == -1)
    fatal ("Error in accept(): %s", strerror (errno));

  ecbp = (ecb *) xmalloc (sizeof (ecb));
  ecbp->do_read = do_read;
  ecbp->buf = NULL;
  ecbp->bufsiz = 0;

  ke_change (s, EVFILT_READ, EV_ADD | EV_ENABLE, ecbp);
}
コード例 #8
0
static void eventer_kqueue_impl_trigger(eventer_t e, int mask) {
  ev_lock_state_t lockstate;
  struct timeval __now;
  int oldmask, newmask;
  const char *cbname;
  int fd;

  fd = e->fd;
  if(e != master_fds[fd].e) return;
  lockstate = acquire_master_fd(fd);
  if(lockstate == EV_ALREADY_OWNED) return;
  assert(lockstate == EV_OWNED);

  gettimeofday(&__now, NULL);
  /* We're going to lie to ourselves.  You'd think this should be:
   * oldmask = e->mask;  However, we just fired with masks[fd], so
   * kqueue is clearly looking for all of the events in masks[fd].
   * So, we combine them "just to be safe."
   */
  oldmask = e->mask | masks[fd];
  cbname = eventer_name_for_callback(e->callback);
  noitLT(eventer_deb, &__now, "kqueue: fire on %d/%x to %s(%p)\n",
         fd, masks[fd], cbname?cbname:"???", e->callback);
  newmask = e->callback(e, mask, e->closure, &__now);

  if(newmask) {
    /* toggle the read bits if needed */
    if(newmask & (EVENTER_READ | EVENTER_EXCEPTION)) {
      if(!(oldmask & (EVENTER_READ | EVENTER_EXCEPTION)))
        ke_change(fd, EVFILT_READ, EV_ADD | EV_ENABLE, e);
    }
    else if(oldmask & (EVENTER_READ | EVENTER_EXCEPTION))
      ke_change(fd, EVFILT_READ, EV_DELETE | EV_DISABLE, e);

    /* toggle the write bits if needed */
    if(newmask & EVENTER_WRITE) {
      if(!(oldmask & EVENTER_WRITE))
        ke_change(fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, e);
    }
    else if(oldmask & EVENTER_WRITE)
      ke_change(fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, e);

    /* Set our mask */
    e->mask = newmask;
  }
  else {
    /*
     * Long story long:
     *  When integrating with a few external event systems, we find
     *  it difficult to make their use of remove+add as an update
     *  as it can be recurrent in a single handler call and you cannot
     *  remove completely from the event system if you are going to
     *  just update (otherwise the eventer_t in your call stack could
     *  be stale).  What we do is perform a superficial remove, marking
     *  the mask as 0, but not eventer_remove_fd.  Then on an add, if
     *  we already have an event, we just update the mask (as we
     *  have not yet returned to the eventer's loop.
     *  This leaves us in a tricky situation when a remove is called
     *  and the add doesn't roll in, we return 0 (mask == 0) and hit
     *  this spot.  We have intended to remove the event, but it still
     *  resides at master_fds[fd].e -- even after we free it.
     *  So, in the evnet that we return 0 and the event that
     *  master_fds[fd].e == the event we're about to free... we NULL
     *  it out.
     */
    if(master_fds[fd].e == e) master_fds[fd].e = NULL;
    eventer_free(e);
  }
  release_master_fd(fd, lockstate);
}
コード例 #9
0
int
main (register int const argc, register char *const argv[])
{
  auto in_addr listen_addr;
  register int optch;
  auto int one = 1;
  register int portno = 0;
  register int option_errors = 0;
  register int server_sock;
  auto sockaddr_in sin;
  register servent *servp;
  auto ecb listen_ecb;
  register int kq;

  pname = strrchr (argv[0], '/');
  pname = pname ? pname+1 : argv[0];

  listen_addr.s_addr = htonl (INADDR_ANY);  /* Default.  */

  while ((optch = getopt (argc, argv, "p:")) != EOF)
    {
      switch (optch)
        {
        case 'p':
          if (strlen (optarg) == 0 || !all_digits (optarg))
            {
              error ("Invalid argument for -p option: %s", optarg);
              option_errors++;
            }
          portno = atoi (optarg);
          if (portno == 0 || portno >= (1u << 16))
            {
              error ("Invalid argument for -p option: %s", optarg);
              option_errors++;
            }
          break;
	default:
          error ("Invalid option: -%c", optch);
          option_errors++;
        }
    }

  if (option_errors || optind != argc)
    usage ();

  if (daemon(0,0) < 0)
	perror("daemon failed");

  if (portno == 0)
    {
      if ((servp = getservbyname (servname, protoname)) == NULL)
        fatal ("Error getting port number for service `%s': %s",
               servname, strerror (errno));
      portno = ntohs (servp->s_port);
    }

  if ((server_sock = socket (PF_INET, SOCK_STREAM, 0)) == -1)
    fatal ("Error creating socket: %s", strerror (errno));

  if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) == -1)
    fatal ("Error setting SO_REUSEADDR for socket: %s", strerror (errno));

  memset (&sin, 0, sizeof sin);
  sin.sin_family = AF_INET;
  sin.sin_addr = listen_addr;
  sin.sin_port = htons (portno);

  if (bind (server_sock, (const struct sockaddr *)&sin, sizeof sin) == -1)
    fatal ("Error binding socket: %s", strerror (errno));

  if (listen (server_sock, 20) == -1)
    fatal ("Error listening to socket: %s", strerror (errno));

  if ((kq = kqueue ()) == -1)
    fatal ("Error creating kqueue: %s", strerror (errno));

  listen_ecb.do_read = do_accept;
  listen_ecb.buf = NULL;
  listen_ecb.buf = 0;

  ke_change (server_sock, EVFILT_READ, EV_ADD | EV_ENABLE, &listen_ecb);

  event_loop (kq);
}