xref: /libev/ev_poll.c (revision 93823e6c)
1e3a38431SPaul Bohm /*
2e3a38431SPaul Bohm  * libev poll fd activity backend
3e3a38431SPaul Bohm  *
4e3a38431SPaul Bohm  * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <[email protected]>
5e3a38431SPaul Bohm  * All rights reserved.
6e3a38431SPaul Bohm  *
7e3a38431SPaul Bohm  * Redistribution and use in source and binary forms, with or without modifica-
8e3a38431SPaul Bohm  * tion, are permitted provided that the following conditions are met:
9e3a38431SPaul Bohm  *
10e3a38431SPaul Bohm  *   1.  Redistributions of source code must retain the above copyright notice,
11e3a38431SPaul Bohm  *       this list of conditions and the following disclaimer.
12e3a38431SPaul Bohm  *
13e3a38431SPaul Bohm  *   2.  Redistributions in binary form must reproduce the above copyright
14e3a38431SPaul Bohm  *       notice, this list of conditions and the following disclaimer in the
15e3a38431SPaul Bohm  *       documentation and/or other materials provided with the distribution.
16e3a38431SPaul Bohm  *
17e3a38431SPaul Bohm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18e3a38431SPaul Bohm  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19e3a38431SPaul Bohm  * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
20e3a38431SPaul Bohm  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21e3a38431SPaul Bohm  * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22e3a38431SPaul Bohm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23e3a38431SPaul Bohm  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24e3a38431SPaul Bohm  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
25e3a38431SPaul Bohm  * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26e3a38431SPaul Bohm  * OF THE POSSIBILITY OF SUCH DAMAGE.
27e3a38431SPaul Bohm  *
28e3a38431SPaul Bohm  * Alternatively, the contents of this file may be used under the terms of
29e3a38431SPaul Bohm  * the GNU General Public License ("GPL") version 2 or any later version,
30e3a38431SPaul Bohm  * in which case the provisions of the GPL are applicable instead of
31e3a38431SPaul Bohm  * the above. If you wish to allow the use of your version of this file
32e3a38431SPaul Bohm  * only under the terms of the GPL and not to allow others to use your
33e3a38431SPaul Bohm  * version of this file under the BSD license, indicate your decision
34e3a38431SPaul Bohm  * by deleting the provisions above and replace them with the notice
35e3a38431SPaul Bohm  * and other provisions required by the GPL. If you do not delete the
36e3a38431SPaul Bohm  * provisions above, a recipient may use your version of this file under
37e3a38431SPaul Bohm  * either the BSD or the GPL.
38e3a38431SPaul Bohm  */
39e3a38431SPaul Bohm 
40e3a38431SPaul Bohm #include <poll.h>
41e3a38431SPaul Bohm 
42e3a38431SPaul Bohm void inline_size
pollidx_init(int * base,int count)43e3a38431SPaul Bohm pollidx_init (int *base, int count)
44e3a38431SPaul Bohm {
45e3a38431SPaul Bohm   /* consider using memset (.., -1, ...), which is practically guaranteed
46e3a38431SPaul Bohm    * to work on all systems implementing poll */
47e3a38431SPaul Bohm   while (count--)
48e3a38431SPaul Bohm     *base++ = -1;
49e3a38431SPaul Bohm }
50e3a38431SPaul Bohm 
51e3a38431SPaul Bohm static void
poll_modify(EV_P_ int fd,int oev,int nev)52e3a38431SPaul Bohm poll_modify (EV_P_ int fd, int oev, int nev)
53e3a38431SPaul Bohm {
54e3a38431SPaul Bohm   int idx;
55e3a38431SPaul Bohm 
56e3a38431SPaul Bohm   if (oev == nev)
57e3a38431SPaul Bohm     return;
58e3a38431SPaul Bohm 
59e3a38431SPaul Bohm   array_needsize (int, pollidxs, pollidxmax, fd + 1, pollidx_init);
60e3a38431SPaul Bohm 
61e3a38431SPaul Bohm   idx = pollidxs [fd];
62e3a38431SPaul Bohm 
63e3a38431SPaul Bohm   if (idx < 0) /* need to allocate a new pollfd */
64e3a38431SPaul Bohm     {
65e3a38431SPaul Bohm       pollidxs [fd] = idx = pollcnt++;
66e3a38431SPaul Bohm       array_needsize (struct pollfd, polls, pollmax, pollcnt, EMPTY2);
67e3a38431SPaul Bohm       polls [idx].fd = fd;
68e3a38431SPaul Bohm     }
69e3a38431SPaul Bohm 
70e3a38431SPaul Bohm   assert (polls [idx].fd == fd);
71e3a38431SPaul Bohm 
72e3a38431SPaul Bohm   if (nev)
73e3a38431SPaul Bohm     polls [idx].events =
74e3a38431SPaul Bohm         (nev & EV_READ ? POLLIN : 0)
75e3a38431SPaul Bohm         | (nev & EV_WRITE ? POLLOUT : 0);
76e3a38431SPaul Bohm   else /* remove pollfd */
77e3a38431SPaul Bohm     {
78e3a38431SPaul Bohm       pollidxs [fd] = -1;
79e3a38431SPaul Bohm 
80e3a38431SPaul Bohm       if (expect_true (idx < --pollcnt))
81e3a38431SPaul Bohm         {
82e3a38431SPaul Bohm           polls [idx] = polls [pollcnt];
83e3a38431SPaul Bohm           pollidxs [polls [idx].fd] = idx;
84e3a38431SPaul Bohm         }
85e3a38431SPaul Bohm     }
86e3a38431SPaul Bohm }
87e3a38431SPaul Bohm 
88e3a38431SPaul Bohm static void
poll_poll(EV_P_ ev_tstamp timeout)89e3a38431SPaul Bohm poll_poll (EV_P_ ev_tstamp timeout)
90e3a38431SPaul Bohm {
91e3a38431SPaul Bohm   struct pollfd *p;
92e3a38431SPaul Bohm   int res;
93e3a38431SPaul Bohm 
94e3a38431SPaul Bohm   EV_RELEASE_CB;
95*93823e6cSPaul Bohm   res = poll (polls, pollcnt, timeout * 1e3);
96e3a38431SPaul Bohm   EV_ACQUIRE_CB;
97e3a38431SPaul Bohm 
98e3a38431SPaul Bohm   if (expect_false (res < 0))
99e3a38431SPaul Bohm     {
100e3a38431SPaul Bohm       if (errno == EBADF)
101e3a38431SPaul Bohm         fd_ebadf (EV_A);
102e3a38431SPaul Bohm       else if (errno == ENOMEM && !syserr_cb)
103e3a38431SPaul Bohm         fd_enomem (EV_A);
104e3a38431SPaul Bohm       else if (errno != EINTR)
105e3a38431SPaul Bohm         ev_syserr ("(libev) poll");
106e3a38431SPaul Bohm     }
107e3a38431SPaul Bohm   else
108e3a38431SPaul Bohm     for (p = polls; res; ++p)
109e3a38431SPaul Bohm       {
110e3a38431SPaul Bohm         assert (("libev: poll() returned illegal result, broken BSD kernel?", p < polls + pollcnt));
111e3a38431SPaul Bohm 
112e3a38431SPaul Bohm         if (expect_false (p->revents)) /* this expect is debatable */
113e3a38431SPaul Bohm           {
114e3a38431SPaul Bohm             --res;
115e3a38431SPaul Bohm 
116e3a38431SPaul Bohm             if (expect_false (p->revents & POLLNVAL))
117e3a38431SPaul Bohm               fd_kill (EV_A_ p->fd);
118e3a38431SPaul Bohm             else
119e3a38431SPaul Bohm               fd_event (
120e3a38431SPaul Bohm                 EV_A_
121e3a38431SPaul Bohm                 p->fd,
122e3a38431SPaul Bohm                 (p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
123e3a38431SPaul Bohm                 | (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
124e3a38431SPaul Bohm               );
125e3a38431SPaul Bohm           }
126e3a38431SPaul Bohm       }
127e3a38431SPaul Bohm }
128e3a38431SPaul Bohm 
129e3a38431SPaul Bohm int inline_size
poll_init(EV_P_ int flags)130e3a38431SPaul Bohm poll_init (EV_P_ int flags)
131e3a38431SPaul Bohm {
132*93823e6cSPaul Bohm   backend_mintime = 1e-3;
133e3a38431SPaul Bohm   backend_modify  = poll_modify;
134e3a38431SPaul Bohm   backend_poll    = poll_poll;
135e3a38431SPaul Bohm 
136e3a38431SPaul Bohm   pollidxs = 0; pollidxmax = 0;
137e3a38431SPaul Bohm   polls    = 0; pollmax    = 0; pollcnt = 0;
138e3a38431SPaul Bohm 
139e3a38431SPaul Bohm   return EVBACKEND_POLL;
140e3a38431SPaul Bohm }
141e3a38431SPaul Bohm 
142e3a38431SPaul Bohm void inline_size
poll_destroy(EV_P)143e3a38431SPaul Bohm poll_destroy (EV_P)
144e3a38431SPaul Bohm {
145e3a38431SPaul Bohm   ev_free (pollidxs);
146e3a38431SPaul Bohm   ev_free (polls);
147e3a38431SPaul Bohm }
148e3a38431SPaul Bohm 
149