xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

ospoll.c (19592B)


      1 /*
      2  * Copyright © 2016 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that copyright
      7  * notice and this permission notice appear in supporting documentation, and
      8  * that the name of the copyright holders not be used in advertising or
      9  * publicity pertaining to distribution of the software without specific,
     10  * written prior permission.  The copyright holders make no representations
     11  * about the suitability of this software for any purpose.  It is provided "as
     12  * is" without express or implied warranty.
     13  *
     14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     20  * OF THIS SOFTWARE.
     21  */
     22 
     23 #ifdef HAVE_DIX_CONFIG_H
     24 #include <dix-config.h>
     25 #endif
     26 
     27 #include <X11/X.h>
     28 #include <X11/Xproto.h>
     29 #include <stdlib.h>
     30 #include <unistd.h>
     31 #include "misc.h"               /* for typedef of pointer */
     32 #include "ospoll.h"
     33 #include "list.h"
     34 
     35 #if !HAVE_OSPOLL && defined(HAVE_POLLSET_CREATE)
     36 #include <sys/pollset.h>
     37 #define POLLSET         1
     38 #define HAVE_OSPOLL     1
     39 #endif
     40 
     41 #if !HAVE_OSPOLL && defined(HAVE_PORT_CREATE)
     42 #include <port.h>
     43 #include <poll.h>
     44 #define PORT            1
     45 #define HAVE_OSPOLL     1
     46 #endif
     47 
     48 #if !HAVE_OSPOLL && defined(HAVE_EPOLL_CREATE1)
     49 #include <sys/epoll.h>
     50 #define EPOLL           1
     51 #define HAVE_OSPOLL     1
     52 #endif
     53 
     54 #if !HAVE_OSPOLL
     55 #include "xserver_poll.h"
     56 #define POLL            1
     57 #define HAVE_OSPOLL     1
     58 #endif
     59 
     60 #if POLLSET
     61 
     62 // pollset-based implementation (as seen on AIX)
     63 struct ospollfd {
     64     int                 fd;
     65     int                 xevents;
     66     short               revents;
     67     enum ospoll_trigger trigger;
     68     void                (*callback)(int fd, int xevents, void *data);
     69     void                *data;
     70 };
     71 
     72 struct ospoll {
     73     pollset_t           ps;
     74     struct ospollfd     *fds;
     75     int                 num;
     76     int                 size;
     77 };
     78 
     79 #endif
     80 
     81 #if EPOLL || PORT
     82 
     83 /* epoll-based implementation */
     84 struct ospollfd {
     85     int                 fd;
     86     int                 xevents;
     87     enum ospoll_trigger trigger;
     88     void                (*callback)(int fd, int xevents, void *data);
     89     void                *data;
     90     struct xorg_list    deleted;
     91 };
     92 
     93 struct ospoll {
     94     int                 epoll_fd;
     95     struct ospollfd     **fds;
     96     int                 num;
     97     int                 size;
     98     struct xorg_list    deleted;
     99 };
    100 
    101 #endif
    102 
    103 #if POLL
    104 
    105 /* poll-based implementation */
    106 struct ospollfd {
    107     short               revents;
    108     enum ospoll_trigger trigger;
    109     void                (*callback)(int fd, int revents, void *data);
    110     void                *data;
    111 };
    112 
    113 struct ospoll {
    114     struct pollfd       *fds;
    115     struct ospollfd     *osfds;
    116     int                 num;
    117     int                 size;
    118     Bool                changed;
    119 };
    120 
    121 #endif
    122 
    123 /* Binary search for the specified file descriptor
    124  *
    125  * Returns position if found
    126  * Returns -position - 1 if not found
    127  */
    128 
    129 static int
    130 ospoll_find(struct ospoll *ospoll, int fd)
    131 {
    132     int lo = 0;
    133     int hi = ospoll->num - 1;
    134 
    135     while (lo <= hi) {
    136         int m = (lo + hi) >> 1;
    137 #if EPOLL || PORT
    138         int t = ospoll->fds[m]->fd;
    139 #endif
    140 #if POLL || POLLSET
    141         int t = ospoll->fds[m].fd;
    142 #endif
    143 
    144         if (t < fd)
    145             lo = m + 1;
    146         else if (t > fd)
    147             hi = m - 1;
    148         else
    149             return m;
    150     }
    151     return -(lo + 1);
    152 }
    153 
    154 #if EPOLL || PORT
    155 static void
    156 ospoll_clean_deleted(struct ospoll *ospoll)
    157 {
    158     struct ospollfd     *osfd, *tmp;
    159 
    160     xorg_list_for_each_entry_safe(osfd, tmp, &ospoll->deleted, deleted) {
    161         xorg_list_del(&osfd->deleted);
    162         free(osfd);
    163     }
    164 }
    165 #endif
    166 
    167 /* Insert an element into an array
    168  *
    169  * base: base address of array
    170  * num:  number of elements in the array before the insert
    171  * size: size of each element
    172  * pos:  position to insert at
    173  */
    174 static inline void
    175 array_insert(void *base, size_t num, size_t size, size_t pos)
    176 {
    177     char *b = base;
    178 
    179     memmove(b + (pos+1) * size,
    180             b + pos * size,
    181             (num - pos) * size);
    182 }
    183 
    184 /* Delete an element from an array
    185  *
    186  * base: base address of array
    187  * num:  number of elements in the array before the delete
    188  * size: size of each element
    189  * pos:  position to delete from
    190  */
    191 static inline void
    192 array_delete(void *base, size_t num, size_t size, size_t pos)
    193 {
    194     char *b = base;
    195 
    196     memmove(b + pos * size, b + (pos + 1) * size,
    197             (num - pos - 1) * size);
    198 }
    199 
    200 
    201 struct ospoll *
    202 ospoll_create(void)
    203 {
    204 #if POLLSET
    205     struct ospoll *ospoll = calloc(1, sizeof (struct ospoll));
    206 
    207     ospoll->ps = pollset_create(-1);
    208     if (ospoll->ps < 0) {
    209         free (ospoll);
    210         return NULL;
    211     }
    212     return ospoll;
    213 #endif
    214 #if PORT
    215     struct ospoll *ospoll = calloc(1, sizeof (struct ospoll));
    216 
    217     ospoll->epoll_fd = port_create();
    218     if (ospoll->epoll_fd < 0) {
    219         free (ospoll);
    220         return NULL;
    221     }
    222     xorg_list_init(&ospoll->deleted);
    223     return ospoll;
    224 #endif
    225 #if EPOLL
    226     struct ospoll       *ospoll = calloc(1, sizeof (struct ospoll));
    227 
    228     ospoll->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    229     if (ospoll->epoll_fd < 0) {
    230         free (ospoll);
    231         return NULL;
    232     }
    233     xorg_list_init(&ospoll->deleted);
    234     return ospoll;
    235 #endif
    236 #if POLL
    237     return calloc(1, sizeof (struct ospoll));
    238 #endif
    239 }
    240 
    241 void
    242 ospoll_destroy(struct ospoll *ospoll)
    243 {
    244 #if POLLSET
    245     if (ospoll) {
    246         assert (ospoll->num == 0);
    247         pollset_destroy(ospoll->ps);
    248         free(ospoll->fds);
    249         free(ospoll);
    250     }
    251 #endif
    252 #if EPOLL || PORT
    253     if (ospoll) {
    254         assert (ospoll->num == 0);
    255         close(ospoll->epoll_fd);
    256         ospoll_clean_deleted(ospoll);
    257         free(ospoll->fds);
    258         free(ospoll);
    259     }
    260 #endif
    261 #if POLL
    262     if (ospoll) {
    263         assert (ospoll->num == 0);
    264         free (ospoll->fds);
    265         free (ospoll->osfds);
    266         free (ospoll);
    267     }
    268 #endif
    269 }
    270 
    271 Bool
    272 ospoll_add(struct ospoll *ospoll, int fd,
    273            enum ospoll_trigger trigger,
    274            void (*callback)(int fd, int xevents, void *data),
    275            void *data)
    276 {
    277     int pos = ospoll_find(ospoll, fd);
    278 #if POLLSET
    279     if (pos < 0) {
    280         if (ospoll->num == ospoll->size) {
    281             struct ospollfd *new_fds;
    282             int new_size = ospoll->size ? ospoll->size * 2 : MAXCLIENTS * 2;
    283 
    284             new_fds = reallocarray(ospoll->fds, new_size, sizeof (ospoll->fds[0]));
    285             if (!new_fds)
    286                 return FALSE;
    287             ospoll->fds = new_fds;
    288             ospoll->size = new_size;
    289         }
    290         pos = -pos - 1;
    291         array_insert(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
    292         ospoll->num++;
    293 
    294         ospoll->fds[pos].fd = fd;
    295         ospoll->fds[pos].xevents = 0;
    296         ospoll->fds[pos].revents = 0;
    297     }
    298     ospoll->fds[pos].trigger = trigger;
    299     ospoll->fds[pos].callback = callback;
    300     ospoll->fds[pos].data = data;
    301 #endif
    302 #if PORT
    303     struct ospollfd *osfd;
    304 
    305     if (pos < 0) {
    306         osfd = calloc(1, sizeof (struct ospollfd));
    307         if (!osfd)
    308             return FALSE;
    309 
    310         if (ospoll->num >= ospoll->size) {
    311             struct ospollfd **new_fds;
    312             int new_size = ospoll->size ? ospoll->size * 2 : MAXCLIENTS * 2;
    313 
    314             new_fds = reallocarray(ospoll->fds, new_size, sizeof (ospoll->fds[0]));
    315             if (!new_fds) {
    316                 free (osfd);
    317                 return FALSE;
    318             }
    319             ospoll->fds = new_fds;
    320             ospoll->size = new_size;
    321         }
    322 
    323         osfd->fd = fd;
    324         osfd->xevents = 0;
    325 
    326         pos = -pos - 1;
    327         array_insert(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
    328         ospoll->fds[pos] = osfd;
    329         ospoll->num++;
    330     } else {
    331         osfd = ospoll->fds[pos];
    332     }
    333     osfd->data = data;
    334     osfd->callback = callback;
    335     osfd->trigger = trigger;
    336 #endif
    337 #if EPOLL
    338     struct ospollfd *osfd;
    339 
    340     if (pos < 0) {
    341 
    342         struct epoll_event ev;
    343 
    344         osfd = calloc(1, sizeof (struct ospollfd));
    345         if (!osfd)
    346             return FALSE;
    347 
    348         if (ospoll->num >= ospoll->size) {
    349             struct ospollfd **new_fds;
    350             int new_size = ospoll->size ? ospoll->size * 2 : MAXCLIENTS * 2;
    351 
    352             new_fds = reallocarray(ospoll->fds, new_size, sizeof (ospoll->fds[0]));
    353             if (!new_fds) {
    354                 free (osfd);
    355                 return FALSE;
    356             }
    357             ospoll->fds = new_fds;
    358             ospoll->size = new_size;
    359         }
    360 
    361         ev.events = 0;
    362         ev.data.ptr = osfd;
    363         if (trigger == ospoll_trigger_edge)
    364             ev.events |= EPOLLET;
    365         if (epoll_ctl(ospoll->epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
    366             free(osfd);
    367             return FALSE;
    368         }
    369         osfd->fd = fd;
    370         osfd->xevents = 0;
    371 
    372         pos = -pos - 1;
    373         array_insert(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
    374         ospoll->fds[pos] = osfd;
    375         ospoll->num++;
    376     } else {
    377         osfd = ospoll->fds[pos];
    378     }
    379     osfd->data = data;
    380     osfd->callback = callback;
    381     osfd->trigger = trigger;
    382 #endif
    383 #if POLL
    384     if (pos < 0) {
    385         if (ospoll->num == ospoll->size) {
    386             struct pollfd   *new_fds;
    387             struct ospollfd *new_osfds;
    388             int             new_size = ospoll->size ? ospoll->size * 2 : MAXCLIENTS * 2;
    389 
    390             new_fds = reallocarray(ospoll->fds, new_size, sizeof (ospoll->fds[0]));
    391             if (!new_fds)
    392                 return FALSE;
    393             ospoll->fds = new_fds;
    394             new_osfds = reallocarray(ospoll->osfds, new_size, sizeof (ospoll->osfds[0]));
    395             if (!new_osfds)
    396                 return FALSE;
    397             ospoll->osfds = new_osfds;
    398             ospoll->size = new_size;
    399         }
    400         pos = -pos - 1;
    401         array_insert(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
    402         array_insert(ospoll->osfds, ospoll->num, sizeof (ospoll->osfds[0]), pos);
    403         ospoll->num++;
    404         ospoll->changed = TRUE;
    405 
    406         ospoll->fds[pos].fd = fd;
    407         ospoll->fds[pos].events = 0;
    408         ospoll->fds[pos].revents = 0;
    409         ospoll->osfds[pos].revents = 0;
    410     }
    411     ospoll->osfds[pos].trigger = trigger;
    412     ospoll->osfds[pos].callback = callback;
    413     ospoll->osfds[pos].data = data;
    414 #endif
    415     return TRUE;
    416 }
    417 
    418 void
    419 ospoll_remove(struct ospoll *ospoll, int fd)
    420 {
    421     int pos = ospoll_find(ospoll, fd);
    422 
    423     pos = ospoll_find(ospoll, fd);
    424     if (pos >= 0) {
    425 #if POLLSET
    426         struct ospollfd *osfd = &ospoll->fds[pos];
    427         struct poll_ctl ctl = { .cmd = PS_DELETE, .fd = fd };
    428         pollset_ctl(ospoll->ps, &ctl, 1);
    429 
    430         array_delete(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
    431         ospoll->num--;
    432 #endif
    433 #if PORT
    434         struct ospollfd *osfd = ospoll->fds[pos];
    435         port_dissociate(ospoll->epoll_fd, PORT_SOURCE_FD, fd);
    436 
    437         array_delete(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
    438         ospoll->num--;
    439         osfd->callback = NULL;
    440         osfd->data = NULL;
    441         xorg_list_add(&osfd->deleted, &ospoll->deleted);
    442 #endif
    443 #if EPOLL
    444         struct ospollfd *osfd = ospoll->fds[pos];
    445         struct epoll_event ev;
    446         ev.events = 0;
    447         ev.data.ptr = osfd;
    448         (void) epoll_ctl(ospoll->epoll_fd, EPOLL_CTL_DEL, fd, &ev);
    449 
    450         array_delete(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
    451         ospoll->num--;
    452         osfd->callback = NULL;
    453         osfd->data = NULL;
    454         xorg_list_add(&osfd->deleted, &ospoll->deleted);
    455 #endif
    456 #if POLL
    457         array_delete(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
    458         array_delete(ospoll->osfds, ospoll->num, sizeof (ospoll->osfds[0]), pos);
    459         ospoll->num--;
    460         ospoll->changed = TRUE;
    461 #endif
    462     }
    463 }
    464 
    465 #if PORT
    466 static void
    467 epoll_mod(struct ospoll *ospoll, struct ospollfd *osfd)
    468 {
    469     int events = 0;
    470     if (osfd->xevents & X_NOTIFY_READ)
    471         events |= POLLIN;
    472     if (osfd->xevents & X_NOTIFY_WRITE)
    473         events |= POLLOUT;
    474     port_associate(ospoll->epoll_fd, PORT_SOURCE_FD, osfd->fd, events, osfd);
    475 }
    476 #endif
    477 
    478 #if EPOLL
    479 static void
    480 epoll_mod(struct ospoll *ospoll, struct ospollfd *osfd)
    481 {
    482     struct epoll_event ev;
    483     ev.events = 0;
    484     if (osfd->xevents & X_NOTIFY_READ)
    485         ev.events |= EPOLLIN;
    486     if (osfd->xevents & X_NOTIFY_WRITE)
    487         ev.events |= EPOLLOUT;
    488     if (osfd->trigger == ospoll_trigger_edge)
    489         ev.events |= EPOLLET;
    490     ev.data.ptr = osfd;
    491     (void) epoll_ctl(ospoll->epoll_fd, EPOLL_CTL_MOD, osfd->fd, &ev);
    492 }
    493 #endif
    494 
    495 void
    496 ospoll_listen(struct ospoll *ospoll, int fd, int xevents)
    497 {
    498     int pos = ospoll_find(ospoll, fd);
    499 
    500     if (pos >= 0) {
    501 #if POLLSET
    502         struct poll_ctl ctl = { .cmd = PS_MOD, .fd = fd };
    503         if (xevents & X_NOTIFY_READ) {
    504             ctl.events |= POLLIN;
    505             ospoll->fds[pos].revents &= ~POLLIN;
    506         }
    507         if (xevents & X_NOTIFY_WRITE) {
    508             ctl.events |= POLLOUT;
    509             ospoll->fds[pos].revents &= ~POLLOUT;
    510         }
    511         pollset_ctl(ospoll->ps, &ctl, 1);
    512         ospoll->fds[pos].xevents |= xevents;
    513 #endif
    514 #if EPOLL || PORT
    515         struct ospollfd *osfd = ospoll->fds[pos];
    516         osfd->xevents |= xevents;
    517         epoll_mod(ospoll, osfd);
    518 #endif
    519 #if POLL
    520         if (xevents & X_NOTIFY_READ) {
    521             ospoll->fds[pos].events |= POLLIN;
    522             ospoll->osfds[pos].revents &= ~POLLIN;
    523         }
    524         if (xevents & X_NOTIFY_WRITE) {
    525             ospoll->fds[pos].events |= POLLOUT;
    526             ospoll->osfds[pos].revents &= ~POLLOUT;
    527         }
    528 #endif
    529     }
    530 }
    531 
    532 void
    533 ospoll_mute(struct ospoll *ospoll, int fd, int xevents)
    534 {
    535     int pos = ospoll_find(ospoll, fd);
    536 
    537     if (pos >= 0) {
    538 #if POLLSET
    539         struct ospollfd *osfd = &ospoll->fds[pos];
    540         osfd->xevents &= ~xevents;
    541         struct poll_ctl ctl = { .cmd = PS_DELETE, .fd = fd };
    542         pollset_ctl(ospoll->ps, &ctl, 1);
    543         if (osfd->xevents) {
    544             ctl.cmd = PS_ADD;
    545             if (osfd->xevents & X_NOTIFY_READ) {
    546                 ctl.events |= POLLIN;
    547             }
    548             if (osfd->xevents & X_NOTIFY_WRITE) {
    549                 ctl.events |= POLLOUT;
    550             }
    551             pollset_ctl(ospoll->ps, &ctl, 1);
    552         }
    553 #endif
    554 #if EPOLL || PORT
    555         struct ospollfd *osfd = ospoll->fds[pos];
    556         osfd->xevents &= ~xevents;
    557         epoll_mod(ospoll, osfd);
    558 #endif
    559 #if POLL
    560         if (xevents & X_NOTIFY_READ)
    561             ospoll->fds[pos].events &= ~POLLIN;
    562         if (xevents & X_NOTIFY_WRITE)
    563             ospoll->fds[pos].events &= ~POLLOUT;
    564 #endif
    565     }
    566 }
    567 
    568 
    569 int
    570 ospoll_wait(struct ospoll *ospoll, int timeout)
    571 {
    572     int nready;
    573 #if POLLSET
    574 #define MAX_EVENTS      256
    575     struct pollfd events[MAX_EVENTS];
    576 
    577     nready = pollset_poll(ospoll->ps, events, MAX_EVENTS, timeout);
    578     for (int i = 0; i < nready; i++) {
    579         struct pollfd *ev = &events[i];
    580         int pos = ospoll_find(ospoll, ev->fd);
    581         struct ospollfd *osfd = &ospoll->fds[pos];
    582         short revents = ev->revents;
    583         short oldevents = osfd->revents;
    584 
    585         osfd->revents = (revents & (POLLIN|POLLOUT));
    586         if (osfd->trigger == ospoll_trigger_edge)
    587             revents &= ~oldevents;
    588         if (revents) {
    589             int xevents = 0;
    590             if (revents & POLLIN)
    591                 xevents |= X_NOTIFY_READ;
    592             if (revents & POLLOUT)
    593                 xevents |= X_NOTIFY_WRITE;
    594             if (revents & (~(POLLIN|POLLOUT)))
    595                 xevents |= X_NOTIFY_ERROR;
    596             osfd->callback(osfd->fd, xevents, osfd->data);
    597         }
    598     }
    599 #endif
    600 #if PORT
    601 #define MAX_EVENTS      256
    602     port_event_t events[MAX_EVENTS];
    603     uint_t nget = 1;
    604     timespec_t port_timeout = {
    605         .tv_sec = timeout / 1000,
    606         .tv_nsec = (timeout % 1000) * 1000000
    607     };
    608 
    609     nready = 0;
    610     if (port_getn(ospoll->epoll_fd, events, MAX_EVENTS, &nget, &port_timeout)
    611         == 0) {
    612         nready = nget;
    613     }
    614     for (int i = 0; i < nready; i++) {
    615         port_event_t *ev = &events[i];
    616         struct ospollfd *osfd = ev->portev_user;
    617         uint32_t revents = ev->portev_events;
    618         int xevents = 0;
    619 
    620         if (revents & POLLIN)
    621             xevents |= X_NOTIFY_READ;
    622         if (revents & POLLOUT)
    623             xevents |= X_NOTIFY_WRITE;
    624         if (revents & (~(POLLIN|POLLOUT)))
    625             xevents |= X_NOTIFY_ERROR;
    626 
    627         if (osfd->callback)
    628             osfd->callback(osfd->fd, xevents, osfd->data);
    629 
    630         if (osfd->trigger == ospoll_trigger_level &&
    631             !xorg_list_is_empty(&osfd->deleted)) {
    632             epoll_mod(ospoll, osfd);
    633         }
    634     }
    635     ospoll_clean_deleted(ospoll);
    636 #endif
    637 #if EPOLL
    638 #define MAX_EVENTS      256
    639     struct epoll_event events[MAX_EVENTS];
    640     int i;
    641 
    642     nready = epoll_wait(ospoll->epoll_fd, events, MAX_EVENTS, timeout);
    643     for (i = 0; i < nready; i++) {
    644         struct epoll_event *ev = &events[i];
    645         struct ospollfd *osfd = ev->data.ptr;
    646         uint32_t revents = ev->events;
    647         int xevents = 0;
    648 
    649         if (revents & EPOLLIN)
    650             xevents |= X_NOTIFY_READ;
    651         if (revents & EPOLLOUT)
    652             xevents |= X_NOTIFY_WRITE;
    653         if (revents & (~(EPOLLIN|EPOLLOUT)))
    654             xevents |= X_NOTIFY_ERROR;
    655 
    656         if (osfd->callback)
    657             osfd->callback(osfd->fd, xevents, osfd->data);
    658     }
    659     ospoll_clean_deleted(ospoll);
    660 #endif
    661 #if POLL
    662     nready = xserver_poll(ospoll->fds, ospoll->num, timeout);
    663     ospoll->changed = FALSE;
    664     if (nready > 0) {
    665         int f;
    666         for (f = 0; f < ospoll->num; f++) {
    667             short revents = ospoll->fds[f].revents;
    668             short oldevents = ospoll->osfds[f].revents;
    669 
    670             ospoll->osfds[f].revents = (revents & (POLLIN|POLLOUT));
    671             if (ospoll->osfds[f].trigger == ospoll_trigger_edge)
    672                 revents &= ~oldevents;
    673             if (revents) {
    674                 int    xevents = 0;
    675                 if (revents & POLLIN)
    676                     xevents |= X_NOTIFY_READ;
    677                 if (revents & POLLOUT)
    678                     xevents |= X_NOTIFY_WRITE;
    679                 if (revents & (~(POLLIN|POLLOUT)))
    680                     xevents |= X_NOTIFY_ERROR;
    681                 ospoll->osfds[f].callback(ospoll->fds[f].fd, xevents,
    682                                           ospoll->osfds[f].data);
    683 
    684                 /* Check to see if the arrays have changed, and just go back
    685                  * around again
    686                  */
    687                 if (ospoll->changed)
    688                     break;
    689             }
    690         }
    691     }
    692 #endif
    693     return nready;
    694 }
    695 
    696 void
    697 ospoll_reset_events(struct ospoll *ospoll, int fd)
    698 {
    699 #if POLLSET
    700     int pos = ospoll_find(ospoll, fd);
    701 
    702     if (pos < 0)
    703         return;
    704 
    705     ospoll->fds[pos].revents = 0;
    706 #endif
    707 #if PORT
    708     int pos = ospoll_find(ospoll, fd);
    709 
    710     if (pos < 0)
    711         return;
    712 
    713     epoll_mod(ospoll, ospoll->fds[pos]);
    714 #endif
    715 #if POLL
    716     int pos = ospoll_find(ospoll, fd);
    717 
    718     if (pos < 0)
    719         return;
    720 
    721     ospoll->osfds[pos].revents = 0;
    722 #endif
    723 }
    724 
    725 void *
    726 ospoll_data(struct ospoll *ospoll, int fd)
    727 {
    728     int pos = ospoll_find(ospoll, fd);
    729 
    730     if (pos < 0)
    731         return NULL;
    732 #if POLLSET
    733     return ospoll->fds[pos].data;
    734 #endif
    735 #if EPOLL || PORT
    736     return ospoll->fds[pos]->data;
    737 #endif
    738 #if POLL
    739     return ospoll->osfds[pos].data;
    740 #endif
    741 }