ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev_port.c
Revision: 1.28
Committed: Sat Jun 4 05:33:29 2011 UTC (12 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: EV-rel-4_22, rel-4_22, rel-4_20, rxvt-unicode-rel-9_16, EV_rel-4_11, EV_rel-4_10, rel-4_15, rel-4_11, rel-4_18, rel-4_19
Changes since 1.27: +3 -3 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2 root 1.6 * libev solaris event port backend
3     *
4 root 1.25 * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
5 root 1.6 * All rights reserved.
6 root 1.1 *
7 root 1.10 * Redistribution and use in source and binary forms, with or without modifica-
8     * tion, are permitted provided that the following conditions are met:
9 root 1.26 *
10 root 1.10 * 1. Redistributions of source code must retain the above copyright notice,
11     * this list of conditions and the following disclaimer.
12 root 1.26 *
13 root 1.10 * 2. Redistributions in binary form must reproduce the above copyright
14     * notice, this list of conditions and the following disclaimer in the
15     * documentation and/or other materials provided with the distribution.
16 root 1.26 *
17 root 1.10 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19     * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20     * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21     * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
25     * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26     * OF THE POSSIBILITY OF SUCH DAMAGE.
27 root 1.6 *
28 root 1.10 * Alternatively, the contents of this file may be used under the terms of
29     * the GNU General Public License ("GPL") version 2 or any later version,
30     * in which case the provisions of the GPL are applicable instead of
31     * the above. If you wish to allow the use of your version of this file
32     * only under the terms of the GPL and not to allow others to use your
33     * version of this file under the BSD license, indicate your decision
34     * by deleting the provisions above and replace them with the notice
35     * and other provisions required by the GPL. If you do not delete the
36     * provisions above, a recipient may use your version of this file under
37     * either the BSD or the GPL.
38 root 1.1 */
39    
40 root 1.23 /* useful reading:
41     *
42     * http://bugs.opensolaris.org/view_bug.do?bug_id=6268715 (random results)
43     * http://bugs.opensolaris.org/view_bug.do?bug_id=6455223 (just totally broken)
44     * http://bugs.opensolaris.org/view_bug.do?bug_id=6873782 (manpage ETIME)
45     * http://bugs.opensolaris.org/view_bug.do?bug_id=6874410 (implementation ETIME)
46     * http://www.mail-archive.com/networking-discuss@opensolaris.org/msg11898.html ETIME vs. nget
47     * http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/event_port.c (libc)
48     * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/portfs/port.c#1325 (kernel)
49     */
50    
51 root 1.1 #include <sys/types.h>
52     #include <sys/time.h>
53     #include <poll.h>
54     #include <port.h>
55     #include <string.h>
56     #include <errno.h>
57    
58 root 1.9 void inline_speed
59     port_associate_and_check (EV_P_ int fd, int ev)
60     {
61     if (0 >
62     port_associate (
63     backend_fd, PORT_SOURCE_FD, fd,
64     (ev & EV_READ ? POLLIN : 0)
65     | (ev & EV_WRITE ? POLLOUT : 0),
66     0
67     )
68     )
69     {
70     if (errno == EBADFD)
71     fd_kill (EV_A_ fd);
72     else
73 root 1.12 ev_syserr ("(libev) port_associate");
74 root 1.9 }
75     }
76    
77 root 1.1 static void
78     port_modify (EV_P_ int fd, int oev, int nev)
79     {
80     /* we need to reassociate no matter what, as closes are
81     * once more silently being discarded.
82     */
83     if (!nev)
84     {
85     if (oev)
86 root 1.5 port_dissociate (backend_fd, PORT_SOURCE_FD, fd);
87 root 1.1 }
88 root 1.9 else
89     port_associate_and_check (EV_A_ fd, nev);
90 root 1.1 }
91    
92     static void
93     port_poll (EV_P_ ev_tstamp timeout)
94     {
95     int res, i;
96     struct timespec ts;
97     uint_t nget = 1;
98    
99 root 1.23 /* we initialise this to something we will skip in the loop, as */
100     /* port_getn can return with nget unchanged, but no indication */
101     /* whether it was the original value or has been updated :/ */
102     port_events [0].portev_source = 0;
103    
104 root 1.16 EV_RELEASE_CB;
105 root 1.21 EV_TS_SET (ts, timeout);
106 root 1.5 res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts);
107 root 1.16 EV_ACQUIRE_CB;
108 root 1.1
109 root 1.23 /* port_getn may or may not set nget on error */
110     /* so we rely on port_events [0].portev_source not being updated */
111     if (res == -1 && errno != ETIME && errno != EINTR)
112     ev_syserr ("(libev) port_getn (see http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, try LIBEV_FLAGS=3 env variable)");
113 root 1.1
114     for (i = 0; i < nget; ++i)
115     {
116     if (port_events [i].portev_source == PORT_SOURCE_FD)
117     {
118     int fd = port_events [i].portev_object;
119    
120     fd_event (
121     EV_A_
122     fd,
123     (port_events [i].portev_events & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
124     | (port_events [i].portev_events & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
125     );
126    
127 root 1.22 fd_change (EV_A_ fd, EV__IOFDSET);
128 root 1.1 }
129     }
130    
131     if (expect_false (nget == port_eventmax))
132     {
133     ev_free (port_events);
134 root 1.8 port_eventmax = array_nextsize (sizeof (port_event_t), port_eventmax, port_eventmax + 1);
135 root 1.1 port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax);
136     }
137     }
138    
139 root 1.7 int inline_size
140 root 1.1 port_init (EV_P_ int flags)
141     {
142 sf-exg 1.19 /* Initialize the kernel queue */
143 root 1.5 if ((backend_fd = port_create ()) < 0)
144 root 1.1 return 0;
145    
146 root 1.24 assert (("libev: PORT_SOURCE_FD must not be zero", PORT_SOURCE_FD));
147 root 1.23
148 root 1.5 fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */
149 root 1.1
150 root 1.27 /* if my reading of the opensolaris kernel sources are correct, then
151     * opensolaris does something very stupid: it checks if the time has already
152     * elapsed and doesn't round up if that is the case,m otherwise it DOES round
153     * up. Since we can't know what the case is, we need to guess by using a
154     * "large enough" timeout. Normally, 1e-9 would be correct.
155     */
156 root 1.28 backend_mintime = 1e-3; /* needed to compensate for port_getn returning early */
157     backend_modify = port_modify;
158     backend_poll = port_poll;
159 root 1.1
160 sf-exg 1.19 port_eventmax = 64; /* initial number of events receivable per poll */
161 root 1.1 port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax);
162    
163 root 1.3 return EVBACKEND_PORT;
164 root 1.1 }
165    
166 root 1.7 void inline_size
167 root 1.1 port_destroy (EV_P)
168     {
169     ev_free (port_events);
170     }
171    
172 root 1.7 void inline_size
173 root 1.1 port_fork (EV_P)
174     {
175 root 1.5 close (backend_fd);
176 root 1.1
177 root 1.5 while ((backend_fd = port_create ()) < 0)
178 root 1.12 ev_syserr ("(libev) port");
179 root 1.1
180 root 1.5 fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
181 root 1.1
182     /* re-register interest in fds */
183     fd_rearm_all (EV_A);
184     }
185