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