~ubuntu-branches/ubuntu/lucid/libevent/lucid

« back to all changes in this revision

Viewing changes to poll.c

  • Committer: Bazaar Package Importer
  • Author(s): Simon Law
  • Date: 2005-06-27 21:05:46 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20050627210546-ltxijf9i7ttholzh
Tags: 1.1a-1
* New upstream release.
* Acknowledge NMUs.  (Closes: Bug#288282, Bug#288404, Bug#290385, Bug#291096)
* Update README.Debian.  (Closes: Bug#310634)
* libevent.so uses a different library naming scheme now.  We will
  preserve backwards compatiblity with Debian's, but also provide symlinks
  for the official libevent-1.1a.so name.

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
#include <string.h>
46
46
#include <unistd.h>
47
47
#include <errno.h>
48
 
#include <err.h>
49
 
 
50
 
#ifdef USE_LOG
51
 
#include "log.h"
52
 
#else
53
 
#define LOG_DBG(x)
54
 
#define log_error(x)    perror(x)
 
48
#ifdef CHECK_INVARIANTS
 
49
#include <assert.h>
55
50
#endif
56
51
 
57
52
#include "event.h"
58
53
#include "event-internal.h"
59
54
#include "evsignal.h"
 
55
#include "log.h"
60
56
 
61
57
extern volatile sig_atomic_t evsignal_caught;
62
58
 
63
59
struct pollop {
64
60
        int event_count;                /* Highest number alloc */
 
61
        int nfds;                       /* Size of event_* */
 
62
        int fd_count;                   /* Size of idxplus1_by_fd */
65
63
        struct pollfd *event_set;
66
 
        struct event **event_back;
 
64
        struct event **event_r_back;
 
65
        struct event **event_w_back;
 
66
        int *idxplus1_by_fd; /* Index into event_set by fd; we add 1 so
 
67
                              * that 0 (which is easy to memset) can mean
 
68
                              * "no entry." */
67
69
        sigset_t evsigmask;
68
70
};
69
71
 
112
114
        return (evsignal_recalc(&pop->evsigmask));
113
115
}
114
116
 
 
117
#ifdef CHECK_INVARIANTS
 
118
static void
 
119
poll_check_ok(struct pollop *pop)
 
120
{
 
121
        int i, idx;
 
122
        struct event *ev;
 
123
 
 
124
        for (i = 0; i < pop->fd_count; ++i) {
 
125
                idx = pop->idxplus1_by_fd[i]-1;
 
126
                if (idx < 0)
 
127
                        continue;
 
128
                assert(pop->event_set[idx].fd == i);
 
129
                if (pop->event_set[idx].events & POLLIN) {
 
130
                        ev = pop->event_r_back[idx];
 
131
                        assert(ev);
 
132
                        assert(ev->ev_events & EV_READ);
 
133
                        assert(ev->ev_fd == i);
 
134
                }
 
135
                if (pop->event_set[idx].events & POLLOUT) {
 
136
                        ev = pop->event_w_back[idx];
 
137
                        assert(ev);
 
138
                        assert(ev->ev_events & EV_WRITE);
 
139
                        assert(ev->ev_fd == i);
 
140
                }
 
141
        }
 
142
        for (i = 0; i < pop->nfds; ++i) {
 
143
                struct pollfd *pfd = &pop->event_set[i];
 
144
                assert(pop->idxplus1_by_fd[pfd->fd] == i+1);
 
145
        }
 
146
}
 
147
#else
 
148
#define poll_check_ok(pop)
 
149
#endif
 
150
 
115
151
int
116
152
poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
117
153
{
118
 
        int res, i, count, sec, nfds;
119
 
        struct event *ev;
 
154
        int res, i, sec, nfds;
120
155
        struct pollop *pop = arg;
121
156
 
122
 
        count = pop->event_count;
123
 
        nfds = 0;
124
 
        TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
125
 
                if (nfds + 1 >= count) {
126
 
                        if (count < 32)
127
 
                                count = 32;
128
 
                        else
129
 
                                count *= 2;
130
 
 
131
 
                        /* We need more file descriptors */
132
 
                        pop->event_set = realloc(pop->event_set,
133
 
                            count * sizeof(struct pollfd));
134
 
                        if (pop->event_set == NULL) {
135
 
                                log_error("realloc");
136
 
                                return (-1);
137
 
                        }
138
 
                        pop->event_back = realloc(pop->event_back,
139
 
                            count * sizeof(struct event *));
140
 
                        if (pop->event_back == NULL) {
141
 
                                log_error("realloc");
142
 
                                return (-1);
143
 
                        }
144
 
                        pop->event_count = count;
145
 
                }
146
 
                if (ev->ev_events & EV_WRITE) {
147
 
                        struct pollfd *pfd = &pop->event_set[nfds];
148
 
                        pfd->fd = ev->ev_fd;
149
 
                        pfd->events = POLLOUT;
150
 
                        pfd->revents = 0;
151
 
 
152
 
                        pop->event_back[nfds] = ev;
153
 
 
154
 
                        nfds++;
155
 
                }
156
 
                if (ev->ev_events & EV_READ) {
157
 
                        struct pollfd *pfd = &pop->event_set[nfds];
158
 
 
159
 
                        pfd->fd = ev->ev_fd;
160
 
                        pfd->events = POLLIN;
161
 
                        pfd->revents = 0;
162
 
 
163
 
                        pop->event_back[nfds] = ev;
164
 
 
165
 
                        nfds++;
166
 
                }
167
 
        }
168
 
 
169
157
        if (evsignal_deliver(&pop->evsigmask) == -1)
170
158
                return (-1);
171
159
 
 
160
        poll_check_ok(pop);
172
161
        sec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
 
162
        nfds = pop->nfds;
173
163
        res = poll(pop->event_set, nfds, sec);
174
164
 
175
165
        if (evsignal_recalc(&pop->evsigmask) == -1)
177
167
 
178
168
        if (res == -1) {
179
169
                if (errno != EINTR) {
180
 
                        log_error("poll");
 
170
                        event_warn("poll");
181
171
                        return (-1);
182
172
                }
183
173
 
186
176
        } else if (evsignal_caught)
187
177
                evsignal_process();
188
178
 
189
 
        LOG_DBG((LOG_MISC, 80, "%s: poll reports %d", __func__, res));
 
179
        event_debug(("%s: poll reports %d", __func__, res));
190
180
 
191
181
        if (res == 0)
192
182
                return (0);
193
183
 
194
184
        for (i = 0; i < nfds; i++) {
195
185
                int what = pop->event_set[i].revents;
196
 
                
 
186
                struct event *r_ev = NULL, *w_ev = NULL;
 
187
                if (!what)
 
188
                        continue;
 
189
 
197
190
                res = 0;
198
191
 
199
192
                /* If the file gets closed notify */
200
 
                if (what & POLLHUP)
 
193
                if (what & (POLLHUP|POLLERR))
201
194
                        what |= POLLIN|POLLOUT;
202
 
                if (what & POLLERR) 
203
 
                        what |= POLLIN|POLLOUT;
204
 
                if (what & POLLIN)
 
195
                if (what & POLLIN) {
205
196
                        res |= EV_READ;
206
 
                if (what & POLLOUT)
 
197
                        r_ev = pop->event_r_back[i];
 
198
                }
 
199
                if (what & POLLOUT) {
207
200
                        res |= EV_WRITE;
 
201
                        w_ev = pop->event_w_back[i];
 
202
                }
208
203
                if (res == 0)
209
204
                        continue;
210
205
 
211
 
                ev = pop->event_back[i];
212
 
                res &= ev->ev_events;
213
 
 
214
 
                if (res) {
215
 
                        if (!(ev->ev_events & EV_PERSIST))
216
 
                                event_del(ev);
217
 
                        event_active(ev, res, 1);
218
 
                }       
 
206
                if (r_ev && (res & r_ev->ev_events)) {
 
207
                        if (!(r_ev->ev_events & EV_PERSIST))
 
208
                                event_del(r_ev);
 
209
                        event_active(r_ev, res & r_ev->ev_events, 1);
 
210
                }
 
211
                if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
 
212
                        if (!(w_ev->ev_events & EV_PERSIST))
 
213
                                event_del(w_ev);
 
214
                        event_active(w_ev, res & w_ev->ev_events, 1);
 
215
                }
219
216
        }
220
217
 
221
218
        return (0);
225
222
poll_add(void *arg, struct event *ev)
226
223
{
227
224
        struct pollop *pop = arg;
 
225
        struct pollfd *pfd = NULL;
 
226
        int i;
228
227
 
229
228
        if (ev->ev_events & EV_SIGNAL)
230
229
                return (evsignal_add(&pop->evsigmask, ev));
 
230
        if (!(ev->ev_events & (EV_READ|EV_WRITE)))
 
231
                return (0);
 
232
 
 
233
        poll_check_ok(pop);
 
234
        if (pop->nfds + 1 >= pop->event_count) {
 
235
                if (pop->event_count < 32)
 
236
                        pop->event_count = 32;
 
237
                else
 
238
                        pop->event_count *= 2;
 
239
 
 
240
                /* We need more file descriptors */
 
241
                pop->event_set = realloc(pop->event_set,
 
242
                                 pop->event_count * sizeof(struct pollfd));
 
243
                if (pop->event_set == NULL) {
 
244
                        event_warn("realloc");
 
245
                        return (-1);
 
246
                }
 
247
                pop->event_r_back = realloc(pop->event_r_back,
 
248
                            pop->event_count * sizeof(struct event *));
 
249
                pop->event_w_back = realloc(pop->event_w_back,
 
250
                            pop->event_count * sizeof(struct event *));
 
251
                if (pop->event_r_back == NULL ||
 
252
                    pop->event_w_back == NULL) {
 
253
                        event_warn("realloc");
 
254
                        return (-1);
 
255
                }
 
256
        }
 
257
        if (ev->ev_fd >= pop->fd_count) {
 
258
                int new_count;
 
259
                if (pop->fd_count < 32)
 
260
                        new_count = 32;
 
261
                else
 
262
                        new_count = pop->fd_count * 2;
 
263
                while (new_count <= ev->ev_fd)
 
264
                        new_count *= 2;
 
265
                pop->idxplus1_by_fd =
 
266
                        realloc(pop->idxplus1_by_fd, new_count*sizeof(int));
 
267
                if (pop->idxplus1_by_fd == NULL) {
 
268
                        event_warn("realloc");
 
269
                        return (-1);
 
270
                }
 
271
                memset(pop->idxplus1_by_fd + pop->fd_count,
 
272
                       0, sizeof(int)*(new_count - pop->fd_count));
 
273
                pop->fd_count = new_count;
 
274
        }
 
275
 
 
276
        i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
 
277
        if (i >= 0) {
 
278
                pfd = &pop->event_set[i];
 
279
        } else {
 
280
                i = pop->nfds++;
 
281
                pfd = &pop->event_set[i];
 
282
                pfd->events = 0;
 
283
                pfd->fd = ev->ev_fd;
 
284
                pop->event_w_back[i] = pop->event_r_back[i] = NULL;
 
285
                pop->idxplus1_by_fd[ev->ev_fd] = i + 1;
 
286
        }
 
287
 
 
288
        pfd->revents = 0;
 
289
        if (ev->ev_events & EV_WRITE) {
 
290
                pfd->events |= POLLOUT;
 
291
                pop->event_w_back[i] = ev;
 
292
        }
 
293
        if (ev->ev_events & EV_READ) {
 
294
                pfd->events |= POLLIN;
 
295
                pop->event_r_back[i] = ev;
 
296
        }
 
297
        poll_check_ok(pop);
231
298
 
232
299
        return (0);
233
300
}
240
307
poll_del(void *arg, struct event *ev)
241
308
{
242
309
        struct pollop *pop = arg;
243
 
 
244
 
        if (!(ev->ev_events & EV_SIGNAL))
245
 
                return (0);
246
 
 
247
 
        return (evsignal_del(&pop->evsigmask, ev));
 
310
        struct pollfd *pfd = NULL;
 
311
        int i;
 
312
 
 
313
        if (ev->ev_events & EV_SIGNAL)
 
314
                return (evsignal_del(&pop->evsigmask, ev));
 
315
 
 
316
        if (!(ev->ev_events & (EV_READ|EV_WRITE)))
 
317
                return (0);
 
318
 
 
319
        poll_check_ok(pop);
 
320
        i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
 
321
        if (i < 0)
 
322
                return (-1);
 
323
 
 
324
        /* Do we still want to read or write? */
 
325
        pfd = &pop->event_set[i];
 
326
        if (ev->ev_events & EV_READ) {
 
327
                pfd->events &= ~POLLIN;
 
328
                pop->event_r_back[i] = NULL;
 
329
        }
 
330
        if (ev->ev_events & EV_WRITE) {
 
331
                pfd->events &= ~POLLOUT;
 
332
                pop->event_w_back[i] = NULL;
 
333
        }
 
334
        poll_check_ok(pop);
 
335
        if (pfd->events)
 
336
                /* Another event cares about that fd. */
 
337
                return (0);
 
338
 
 
339
        /* Okay, so we aren't interested in that fd anymore. */
 
340
        pop->idxplus1_by_fd[ev->ev_fd] = 0;
 
341
 
 
342
        --pop->nfds;
 
343
        if (i != pop->nfds) {
 
344
                /* 
 
345
                 * Shift the last pollfd down into the now-unoccupied
 
346
                 * position.
 
347
                 */
 
348
                memcpy(&pop->event_set[i], &pop->event_set[pop->nfds],
 
349
                       sizeof(struct pollfd));
 
350
                pop->event_r_back[i] = pop->event_r_back[pop->nfds];
 
351
                pop->event_w_back[i] = pop->event_w_back[pop->nfds];
 
352
                pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1;
 
353
        }
 
354
 
 
355
        poll_check_ok(pop);
 
356
        return (0);
248
357
}