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
ospoll_find(struct ospoll * ospoll,int fd)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
ospoll_clean_deleted(struct ospoll * ospoll)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
array_insert(void * base,size_t num,size_t size,size_t pos)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
array_delete(void * base,size_t num,size_t size,size_t pos)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 *
ospoll_create(void)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
ospoll_destroy(struct ospoll * ospoll)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
ospoll_add(struct ospoll * ospoll,int fd,enum ospoll_trigger trigger,void (* callback)(int fd,int xevents,void * data),void * data)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
ospoll_remove(struct ospoll * ospoll,int fd)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
epoll_mod(struct ospoll * ospoll,struct ospollfd * osfd)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
epoll_mod(struct ospoll * ospoll,struct ospollfd * osfd)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
ospoll_listen(struct ospoll * ospoll,int fd,int xevents)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
ospoll_mute(struct ospoll * ospoll,int fd,int xevents)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
ospoll_wait(struct ospoll * ospoll,int timeout)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
ospoll_reset_events(struct ospoll * ospoll,int fd)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 *
ospoll_data(struct ospoll * ospoll,int fd)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 }
742