ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev_kqueue.c
(Generate patch)

Comparing libev/ev_kqueue.c (file contents):
Revision 1.7 by root, Sun Nov 4 15:58:50 2007 UTC vs.
Revision 1.15 by root, Sun Nov 11 16:59:35 2007 UTC

37static void 37static void
38kqueue_change (EV_P_ int fd, int filter, int flags, int fflags) 38kqueue_change (EV_P_ int fd, int filter, int flags, int fflags)
39{ 39{
40 struct kevent *ke; 40 struct kevent *ke;
41 41
42 array_needsize (kqueue_changes, kqueue_changemax, ++kqueue_changecnt, ); 42 array_needsize (struct kevent, kqueue_changes, kqueue_changemax, ++kqueue_changecnt, );
43 43
44 ke = &kqueue_changes [kqueue_changecnt - 1]; 44 ke = &kqueue_changes [kqueue_changecnt - 1];
45 memset (ke, 0, sizeof (struct kevent)); 45 memset (ke, 0, sizeof (struct kevent));
46 ke->ident = fd; 46 ke->ident = fd;
47 ke->filter = filter; 47 ke->filter = filter;
54#endif 54#endif
55 55
56static void 56static void
57kqueue_modify (EV_P_ int fd, int oev, int nev) 57kqueue_modify (EV_P_ int fd, int oev, int nev)
58{ 58{
59 /* to detect close/reopen reliably, we have to remove and re-add */
60 /* event requests even when oev == nev */
61
59 if ((oev ^ nev) & EV_READ) 62 if (oev & EV_READ)
60 { 63 kqueue_change (EV_A_ fd, EVFILT_READ, EV_DELETE, 0);
64
65 if (oev & EV_WRITE)
66 kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_DELETE, 0);
67
61 if (nev & EV_READ) 68 if (nev & EV_READ)
62 kqueue_change (fd, EVFILT_READ, EV_ADD, NOTE_EOF); 69 kqueue_change (EV_A_ fd, EVFILT_READ, EV_ADD, NOTE_EOF);
63 else
64 kqueue_change (fd, EVFILT_READ, EV_DELETE, 0);
65 }
66 70
67 if ((oev ^ nev) & EV_WRITE)
68 {
69 if (nev & EV_WRITE) 71 if (nev & EV_WRITE)
70 kqueue_change (fd, EVFILT_WRITE, EV_ADD, NOTE_EOF); 72 kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_ADD, NOTE_EOF);
71 else
72 kqueue_change (fd, EVFILT_WRITE, EV_DELETE, 0);
73 }
74} 73}
75 74
76static void 75static void
77kqueue_poll (EV_P_ ev_tstamp timeout) 76kqueue_poll (EV_P_ ev_tstamp timeout)
78{ 77{
79 int res, i; 78 int res, i;
80 struct timespec ts; 79 struct timespec ts;
80
81 /* need to resize so there is enough space for errors */
82 if (kqueue_changecnt > kqueue_eventmax)
83 {
84 ev_free (kqueue_events);
85 kqueue_eventmax = array_roundsize (struct kevent, kqueue_changecnt);
86 kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
87 }
81 88
82 ts.tv_sec = (time_t)timeout; 89 ts.tv_sec = (time_t)timeout;
83 ts.tv_nsec = (long)(timeout - (ev_tstamp)ts.tv_sec) * 1e9; 90 ts.tv_nsec = (long)(timeout - (ev_tstamp)ts.tv_sec) * 1e9;
84 res = kevent (kqueue_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts); 91 res = kevent (kqueue_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts);
85 kqueue_changecnt = 0; 92 kqueue_changecnt = 0;
86 93
87 if (res < 0) 94 if (res < 0)
95 {
96 if (errno != EINTR)
97 syserr ("(libev) kevent");
98
88 return; 99 return;
100 }
89 101
90 for (i = 0; i < res; ++i) 102 for (i = 0; i < res; ++i)
91 { 103 {
104 int fd = kqueue_events [i].ident;
105
92 if (kqueue_events [i].flags & EV_ERROR) 106 if (kqueue_events [i].flags & EV_ERROR)
93 { 107 {
108 int err = kqueue_events [i].data;
109
94 /* 110 /*
95 * Error messages that can happen, when a delete fails. 111 * errors that may happen
96 * EBADF happens when the file discriptor has been 112 * EBADF happens when the file discriptor has been
97 * closed, 113 * closed,
98 * ENOENT when the file discriptor was closed and 114 * ENOENT when the file descriptor was closed and
99 * then reopened. 115 * then reopened.
100 * EINVAL for some reasons not understood; EINVAL 116 * EINVAL for some reasons not understood; EINVAL
101 * should not be returned ever; but FreeBSD does :-\ 117 * should not be returned ever; but FreeBSD does :-\
102 * An error is also indicated when a callback deletes
103 * an event we are still processing. In that case
104 * the data field is set to ENOENT.
105 */ 118 */
106 if (kqueue_events [i].data == EBADF) 119
107 fd_kill (EV_A_ kqueue_events [i].ident); 120 /* we are only interested in errors for fds that we are interested in :) */
121 if (anfds [fd].events)
122 {
123 if (err == ENOENT) /* resubmit changes on ENOENT */
124 kqueue_modify (EV_A_ fd, 0, anfds [fd].events);
125 else if (err == EBADF) /* on EBADF, we re-check the fd */
126 {
127 if (fd_valid (fd))
128 kqueue_modify (EV_A_ fd, 0, anfds [fd].events);
129 else
130 fd_kill (EV_A_ fd);
131 }
132 else /* on all other errors, we error out on the fd */
133 fd_kill (EV_A_ fd);
134 }
108 } 135 }
109 else 136 else
110 fd_event ( 137 fd_event (
111 EV_A_ 138 EV_A_
112 kqueue_events [i].ident, 139 fd,
113 kqueue_events [i].filter == EVFILT_READ ? EV_READ 140 kqueue_events [i].filter == EVFILT_READ ? EV_READ
114 : kqueue_events [i].filter == EVFILT_WRITE ? EV_WRITE 141 : kqueue_events [i].filter == EVFILT_WRITE ? EV_WRITE
115 : 0 142 : 0
116 ); 143 );
117 } 144 }
118 145
119 if (expect_false (res == kqueue_eventmax)) 146 if (expect_false (res == kqueue_eventmax))
120 { 147 {
121 free (kqueue_events); 148 ev_free (kqueue_events);
122 kqueue_eventmax = array_roundsize (kqueue_events, kqueue_eventmax << 1); 149 kqueue_eventmax = array_roundsize (struct kevent, kqueue_eventmax << 1);
123 kqueue_events = malloc (sizeof (struct kevent) * kqueue_eventmax); 150 kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
124 } 151 }
125} 152}
126 153
127static int 154static int
128kqueue_init (EV_P_ int flags) 155kqueue_init (EV_P_ int flags)
157 method_fudge = 1e-3; /* needed to compensate for kevent returning early */ 184 method_fudge = 1e-3; /* needed to compensate for kevent returning early */
158 method_modify = kqueue_modify; 185 method_modify = kqueue_modify;
159 method_poll = kqueue_poll; 186 method_poll = kqueue_poll;
160 187
161 kqueue_eventmax = 64; /* intiial number of events receivable per poll */ 188 kqueue_eventmax = 64; /* intiial number of events receivable per poll */
162 kqueue_events = malloc (sizeof (struct kevent) * kqueue_eventmax); 189 kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
163 190
164 kqueue_changes = 0; 191 kqueue_changes = 0;
165 kqueue_changemax = 0; 192 kqueue_changemax = 0;
166 kqueue_changecnt = 0; 193 kqueue_changecnt = 0;
167 194
171static void 198static void
172kqueue_destroy (EV_P) 199kqueue_destroy (EV_P)
173{ 200{
174 close (kqueue_fd); 201 close (kqueue_fd);
175 202
176 free (kqueue_events); 203 ev_free (kqueue_events);
177 free (kqueue_changes); 204 ev_free (kqueue_changes);
178} 205}
179 206
180static void 207static void
181kqueue_fork (EV_P) 208kqueue_fork (EV_P)
182{ 209{
210 close (kqueue_fd);
211
183 kqueue_fd = kqueue (); 212 while ((kqueue_fd = kqueue ()) < 0)
213 syserr ("(libev) kqueue");
214
184 fcntl (kqueue_fd, F_SETFD, FD_CLOEXEC); 215 fcntl (kqueue_fd, F_SETFD, FD_CLOEXEC);
185 216
186 /* re-register interest in fds */ 217 /* re-register interest in fds */
187 fd_rearm_all (); 218 fd_rearm_all (EV_A);
188} 219}
189 220

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines