Print this page
    
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libc/port/sys/epoll.c
          +++ new/usr/src/lib/libc/port/sys/epoll.c
   1    1  /*
   2    2   * This file and its contents are supplied under the terms of the
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13   13   * Copyright 2016 Joyent, Inc.
  14   14   */
  15   15  
  16   16  #include <sys/types.h>
  17   17  #include <sys/epoll.h>
  18   18  #include <sys/devpoll.h>
  19   19  #include <unistd.h>
  20   20  #include <errno.h>
  21   21  #include <fcntl.h>
  22   22  #include <poll.h>
  23   23  
  24   24  /*
  25   25   * Events that match their epoll(7) equivalents.
  26   26   */
  27   27  #if EPOLLIN != POLLIN
  28   28  #error value of EPOLLIN does not match value of POLLIN
  29   29  #endif
  30   30  
  31   31  #if EPOLLPRI != POLLPRI
  32   32  #error value of EPOLLPRI does not match value of POLLPRI
  33   33  #endif
  34   34  
  35   35  #if EPOLLOUT != POLLOUT
  36   36  #error value of EPOLLOUT does not match value of POLLOUT
  37   37  #endif
  38   38  
  39   39  #if EPOLLRDNORM != POLLRDNORM
  40   40  #error value of EPOLLRDNORM does not match value of POLLRDNORM
  41   41  #endif
  42   42  
  43   43  #if EPOLLRDBAND != POLLRDBAND
  44   44  #error value of EPOLLRDBAND does not match value of POLLRDBAND
  45   45  #endif
  46   46  
  47   47  #if EPOLLERR != POLLERR
  48   48  #error value of EPOLLERR does not match value of POLLERR
  49   49  #endif
  50   50  
  51   51  #if EPOLLHUP != POLLHUP
  52   52  #error value of EPOLLHUP does not match value of POLLHUP
  53   53  #endif
  54   54  
  55   55  /*
  56   56   * Events that we ignore entirely.  They can be set in events, but they will
  57   57   * never be returned.
  58   58   */
  59   59  #define EPOLLIGNORED    (EPOLLMSG | EPOLLWAKEUP)
  60   60  
  61   61  /*
  62   62   * Events that we swizzle into other bit positions.
  63   63   */
  64   64  #define EPOLLSWIZZLED   \
  65   65          (EPOLLRDHUP | EPOLLONESHOT | EPOLLET | EPOLLWRBAND | EPOLLWRNORM)
  66   66  
  67   67  int
  68   68  epoll_create(int size)
  69   69  {
  70   70          int fd;
  71   71  
  72   72          /*
  73   73           * From the epoll_create() man page:  "Since Linux 2.6.8, the size
  74   74           * argument is ignored, but must be greater than zero."  You keep using
  75   75           * that word "ignored"...
  76   76           */
  77   77          if (size <= 0) {
  78   78                  errno = EINVAL;
  79   79                  return (-1);
  80   80          }
  81   81  
  82   82          if ((fd = open("/dev/poll", O_RDWR)) == -1)
  83   83                  return (-1);
  84   84  
  85   85          if (ioctl(fd, DP_EPOLLCOMPAT, 0) == -1) {
  86   86                  (void) close(fd);
  87   87                  return (-1);
  88   88          }
  89   89  
  90   90          return (fd);
  91   91  }
  92   92  
  93   93  int
  94   94  epoll_create1(int flags)
  95   95  {
  96   96          int fd, oflags = O_RDWR;
  97   97  
  98   98          if (flags & EPOLL_CLOEXEC)
  99   99                  oflags |= O_CLOEXEC;
 100  100  
 101  101          if ((fd = open("/dev/poll", oflags)) == -1)
 102  102                  return (-1);
 103  103  
 104  104          if (ioctl(fd, DP_EPOLLCOMPAT, 0) == -1) {
 105  105                  (void) close(fd);
 106  106                  return (-1);
 107  107          }
 108  108  
 109  109          return (fd);
 110  110  }
 111  111  
 112  112  int
 113  113  epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
 114  114  {
 115  115          dvpoll_epollfd_t epoll[2];
 116  116          uint32_t events, ev = 0;
 117  117          int i = 0, res;
 118  118  
 119  119          epoll[i].dpep_pollfd.fd = fd;
 120  120  
 121  121          switch (op) {
 122  122          case EPOLL_CTL_DEL:
 123  123                  ev = POLLREMOVE;
 124  124                  break;
 125  125  
 126  126          case EPOLL_CTL_MOD:
 127  127                  /*
 128  128                   * In the modify case, we pass down two events:  one to
 129  129                   * remove the event and another to add it back.
 130  130                   */
 131  131                  epoll[i++].dpep_pollfd.events = POLLREMOVE;
 132  132                  epoll[i].dpep_pollfd.fd = fd;
 133  133                  /* FALLTHROUGH */
 134  134  
 135  135          case EPOLL_CTL_ADD:
 136  136                  /*
 137  137                   * Mask off the events that we ignore, and then swizzle the
 138  138                   * events for which our values differ from their epoll(7)
 139  139                   * equivalents.
 140  140                   */
 141  141                  events = event->events;
 142  142                  ev = events & ~(EPOLLIGNORED | EPOLLSWIZZLED);
 143  143  
 144  144                  if (events & EPOLLRDHUP)
 145  145                          ev |= POLLRDHUP;
 146  146  
 147  147                  if (events & EPOLLET)
 148  148                          ev |= POLLET;
 149  149  
 150  150                  if (events & EPOLLONESHOT)
 151  151                          ev |= POLLONESHOT;
 152  152  
 153  153                  if (events & EPOLLWRNORM)
 154  154                          ev |= POLLWRNORM;
 155  155  
 156  156                  if (events & EPOLLWRBAND)
 157  157                          ev |= POLLWRBAND;
 158  158  
 159  159                  epoll[i].dpep_data = event->data.u64;
 160  160                  break;
 161  161  
 162  162          default:
 163  163                  errno = EOPNOTSUPP;
 164  164                  return (-1);
 165  165          }
 166  166  
 167  167          epoll[i].dpep_pollfd.events = ev;
 168  168  retry:
 169  169          res = write(epfd, epoll, sizeof (epoll[0]) * (i + 1));
 170  170  
 171  171          if (res == -1) {
 172  172                  if (errno == EINTR) {
 173  173                          /*
 174  174                           * Linux does not document EINTR as an allowed error
 175  175                           * for epoll_ctl.  The write must be retried if it is
 176  176                           * not done automatically via SA_RESTART.
 177  177                           */
 178  178                          goto retry;
 179  179                  }
 180  180                  if (errno == ELOOP) {
 181  181                          /*
 182  182                           * Convert the specific /dev/poll error about an fd
 183  183                           * loop into what is expected from the Linux epoll
 184  184                           * interface.
 185  185                           */
 186  186                          errno = EINVAL;
 187  187                  }
 188  188                  return (-1);
 189  189          }
 190  190          return (0);
 191  191  }
 192  192  
 193  193  int
 194  194  epoll_wait(int epfd, struct epoll_event *events,
 195  195      int maxevents, int timeout)
 196  196  {
 197  197          struct dvpoll arg;
 198  198  
 199  199          if (maxevents <= 0) {
 200  200                  errno = EINVAL;
 201  201                  return (-1);
 202  202          }
 203  203  
 204  204          arg.dp_nfds = maxevents;
 205  205          arg.dp_timeout = timeout;
 206  206          arg.dp_fds = (pollfd_t *)events;
 207  207  
 208  208          return (ioctl(epfd, DP_POLL, &arg));
 209  209  }
 210  210  
 211  211  int
 212  212  epoll_pwait(int epfd, struct epoll_event *events,
 213  213      int maxevents, int timeout, const sigset_t *sigmask)
 214  214  {
 215  215          struct dvpoll arg;
 216  216  
 217  217          if (maxevents <= 0) {
 218  218                  errno = EINVAL;
 219  219                  return (-1);
 220  220          }
 221  221  
 222  222          arg.dp_nfds = maxevents;
 223  223          arg.dp_timeout = timeout;
 224  224          arg.dp_fds = (pollfd_t *)events;
 225  225          arg.dp_setp = (sigset_t *)sigmask;
 226  226  
 227  227          return (ioctl(epfd, DP_PPOLL, &arg));
 228  228  }
  
    | 
      ↓ open down ↓ | 
    228 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX