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.13 by root, Tue Nov 6 17:20:42 2007 UTC vs.
Revision 1.14 by root, Tue Nov 6 18:49:32 2007 UTC

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 (EV_A_ fd, EVFILT_READ, EV_ADD, NOTE_EOF); 69 kqueue_change (EV_A_ fd, EVFILT_READ, EV_ADD, NOTE_EOF);
63 else
64 kqueue_change (EV_A_ 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 (EV_A_ fd, EVFILT_WRITE, EV_ADD, NOTE_EOF); 72 kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_ADD, NOTE_EOF);
71 else
72 kqueue_change (EV_A_ 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 = 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;
92 return; 99 return;
93 } 100 }
94 101
95 for (i = 0; i < res; ++i) 102 for (i = 0; i < res; ++i)
96 { 103 {
104 int fd = kqueue_events [i].ident;
105
97 if (kqueue_events [i].flags & EV_ERROR) 106 if (kqueue_events [i].flags & EV_ERROR)
98 { 107 {
108 int err = kqueue_events [i].data;
109
99 /* 110 /*
100 * Error messages that can happen, when a delete fails. 111 * errors that may happen
101 * EBADF happens when the file discriptor has been 112 * EBADF happens when the file discriptor has been
102 * closed, 113 * closed,
103 * ENOENT when the file discriptor was closed and 114 * ENOENT when the file descriptor was closed and
104 * then reopened. 115 * then reopened.
105 * EINVAL for some reasons not understood; EINVAL 116 * EINVAL for some reasons not understood; EINVAL
106 * should not be returned ever; but FreeBSD does :-\ 117 * should not be returned ever; but FreeBSD does :-\
107 * An error is also indicated when a callback deletes
108 * an event we are still processing. In that case
109 * the data field is set to ENOENT.
110 */ 118 */
111 if (kqueue_events [i].data == EBADF) 119
112 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 }
113 } 135 }
114 else 136 else
115 fd_event ( 137 fd_event (
116 EV_A_ 138 EV_A_
117 kqueue_events [i].ident, 139 fd,
118 kqueue_events [i].filter == EVFILT_READ ? EV_READ 140 kqueue_events [i].filter == EVFILT_READ ? EV_READ
119 : kqueue_events [i].filter == EVFILT_WRITE ? EV_WRITE 141 : kqueue_events [i].filter == EVFILT_WRITE ? EV_WRITE
120 : 0 142 : 0
121 ); 143 );
122 } 144 }
123 145
124 if (expect_false (res == kqueue_eventmax)) 146 if (expect_false (res == kqueue_eventmax))
125 { 147 {
126 ev_free (kqueue_events); 148 ev_free (kqueue_events);
127 kqueue_eventmax = array_roundsize (kqueue_events, kqueue_eventmax << 1); 149 kqueue_eventmax = array_roundsize (struct kevent, kqueue_eventmax << 1);
128 kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax); 150 kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
129 } 151 }
130} 152}
131 153
132static int 154static int

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines